- Install and Setup
- Illumina MiSeq Workflow – Run commands in UNIX
- Ion Torrent PGM Workflow – Run commands in UNIX
- Assign Taxonomy and Filter Results – Run commands in R
- Manual Vetting of Results – Work in a Web Browser
Install and Setup
In the QIIME VB System Settings, we changed default settings to allow 4 cores and 11 GB of virtual memory.
Virtual Box Processor Cores
Virtual Box Memory
If you will be using a similar workflow more than once, it helps to use the time UNIX command in front of other commands. This command returns the processing time, in minutes and seconds, which simply helps plan future data analyses. For example:
Illumina MiSeq Workflow – Run commands in UNIX
If you only have IonTorrent data, skip the [Illumina MiSeq] section and go to the Ion Torrent section
All commands in this section were run inside the QIIME Virtual Box created above in the Install section
1) Organize R1 and R2 Files
First load all compressed R1 and R2 *.fastq.gz paired files into a new folder, such as: 2014MISEQ ####Drag and drop from Windows to Virtual Box or use mv if working directly in UNIX or Macqiime
QIIME will not accept underscores or hyphens in Sample IDs used in the QIIME process, thus, you may have to rename folder names so there are no underscores before L001; change underscores and hyphens to periods, except after L001. Everything before L001 will become the Sample ID. An example of bash code to do this follows:
#!/bin/bash #save this as a script called fixfilenames.sh and save in your Project folder
cd $1;
for file in *L001*; do
fp = "${file%L001*}";
lp = "${file#*L001}";
new = "${fp//_/.}L001$lp";
mv "$file" "$new";
done
Now change permissions and run the script.
cd 2014MISEQ
chmod u+x fixfilenames.sh
./fixfilenames.sh
2) Joined Paired Ends
Next, we join corresponding paired reads (R1 and R2) for each sample to increase read quality and propagate that quality on through to taxonomic assignment.
multiple_join_paired_ends.py -i /home/qiime/2014MISEQ -o /home/qiime/2014MISEQ/joined_seqs
#took 10 secs with test set
We output the joined sequence files, 1 per bat sample, into a new directory called: joined_seqs
Now we take out the unjoined sequences so they do not get mixed up in downstream analyses. You may prefer to save these somewhere if they could be useful to your particular application.
cd joined_seqs #change directory to the newly created joined_seqs directory
find . -name "*.un1.fastq" -type f -delete #do this exactly as written to avoid deleting other files
find . -name "*.un2.fastq" -type f -delete
3) Quality Filter and Assign Sample IDs to Sequences
Illumina MiSeq platform trims Nextera indices and adaptors prior to writing sequence data to BaseSpace. However, we still use QIIME’s split_libraries script to assign Sample IDs to each individual sequence using folder names and concatenate all joined sequences into one file for downstream analyses.
Default quality filtering parameters are applied here so that base calls less than Q25 and sequences less than 200 bp are removed. These paramters can be changed with the -s (min_qual_score) and -l (min_seq_length) options. Our expected length at this step is 211 bp.
cd .. #change directory back to the main working directory
multiple_split_libraries_fastq.py -i /home/qiime/2014MISEQ/joined_seqs -o /home/qiime/2014MISEQ/split_out --demultiplexing_method sampleid_by_file --include_input_dir_path --remove_filepath_in_name #took 16 secs with test set
We output the resulting FASTA file (QIIME uses the file extension .fna) and log files into a new directory called: split_out
This step can take a while to run, so one can make sure QIIME is not hung up by occasionally going into the newly created directory and right clicking on the output file to check file size and make sure it grows between checks. The process is done when the cursor prompt returns to the terminal window.
4) Trim Primers
Now we need to remove Zeale primers from the 5’ and 3’ ends of each sequence. It is easiest to remove the reverse primer first from the 3’ end, then reverse complement the sequences, remove the forward primer which is now in a reverse orientation on the 3’ end, then reverse complement the sequences again so they are back in the 5’ –> 3’ direction with both primers removed.
First we validate the mapping file which tells QIIME what the primer sequences should be.
validate_mapping_file.py -m SampleMapFile.txt #good practice to make sure all columns are in correct format
truncate_reverse_primer.py -f ./split_out/seqs.fna -m ./SampleMapFile.txt -z truncate_remove -M 1 -o ./Rtruncated
The .fna file is our sequence file, and the SampleMapFile.txt is the mapping file with forward and reverse primer sequence info. In this case, we allow 1 mismatch in the primer sequence. The mapping file must have unique barcodes for each sample. Becasue the barcodes are already removed by Illumina, we simply concatenated forward and reverse indexes used in the sequencing process so each sample has a unique ‘barcode’ to satisfy the validate_mapping_file.py:
We reverse complement the sequences using the FASTX Toolkit, which must be installed in our QIIME Virtual Box or directly in Macqiime or Linux in the main working directory, then again remove reverse primers, and flip sequences back. We used a local copy of FASTX Toolkit 0.0.12. Reverse complementing can also be done with the QIIME adjust_seq_orientation.py script. We used the FASTX command because we will use another FASTX tool later in this section.
Note that a separate mapping file is needed with primer sequences also reverse complemented: SampleMapFile_reverse.txt.
fastx_reverse_complement -i ./Rtruncated/seqs_rev_primer_truncated.fna -o ./Rcomp
truncate_reverse_primer.py -f ./Rcomp -m ./SampleMapFile_reverse.txt -z truncate_remove -M 1 -o ./Rcomp_forward_removed
fastx_reverse_complement -i ./Rcomp_forward_removed/Rcomp_rev_primer_truncated.fna -o ./trimmed_seqs.fna
We now have a file called trimmed_seqs.fna with all primers removed.
5) Cluster Similar Sequences
Next we cluster similar sequences using the local alignmnet ‘swarm’ method and allowing only a 2 bp mismatch.
Mahé F, Rognes T, Quince C, de Vargas C, Dunthorn M. (2014) Swarm: robust and fast clustering method for amplicon-based studies. PeerJ 2:e593 http://dx.doi.org/10.7717/peerj.593
pick_otus.py -i ./trimmed_seqs.fna -m swarm --swarm_resolution 2 -o ./swarmOTUs #took 18 sec with test set
Now we have a new directory with the clusters of sequences: swarmOTUs
This step can take a while to run, and no files are produced until the process is complete. One can make sure QIIME is not hung up by using the top UNIX command in a new terminal window. The pick-otus QIIME command should normally be at the top of the list and using the greatest %CPU.
6) Build and Filter OTU Occurrence Table (BIOM)
This scipt creates a new file called exclude.txt that we can use in the next step to remove those low abundance OTU clusters.
The last command in UNIX will convert our final FASTA file to a tab-delimited file we can use to assign taxonomy in the BOLD database. This file will be useful when resolving taxonomic discrepancies in the last section: [Manual Vetting of Results]. The fasta_formatter command is part of the FASTX Toolkit. We run the command and then manually add column headers to the text file called: seqID and seqs.
fasta_formatter -i ./2014_final_no_singletons.fna -o ./2014tabseqs.txt -t
The final 2014tabseqs.txt file will look like this:
| denovo0 F10R12_2 |
AATTTGAGCAG . . . . . |
| denovo1 F10R12_1121 |
AATTTGAGCAGG . . . . . |
| denovo10 F1R13_166841 |
AAGATGAGCTGG . . . . . |
| . . . . . . . . . |
. . . . . |
| denovo789 F10R5_2482 |
AAGATGCCTGGAA . . . . . |
Ion Torrent PGM Workflow – Run commands in UNIX
The Ion Torrent Personal Genome Machine (PGM) is widely used for amplicon sequencing but the raw machine output is different than Illumina. Ion does not use the paired end read system; thus, we keep forward and reverse sequences separate and do not try to join sequences.
1) Organize Forward and Reverse Files
Amplicons are read in either forward or reverse direction, depending on which end attached to the Ion chip. Thus, we expect 1 FASTQ file for each unique barcode used. In our case, we double barcoded samples (n = 50; 46 bat samples + 4 blanks) with 10 unique forward primers and 5 unique reverse primers, so we expect 15 fastq files. We know the files 1–10 were sequenced in the forward direction and files 11–15 were read in the reverse direction. The raw output folder should look like this:
| 2015-03-20.IonXpress_001.fastq |
forward |
| 2015-03-20.IonXpress_002.fastq |
forward |
| 2015-03-20.IonXpress_003.fastq |
forward |
| . . . . . . . . . |
. . . |
| 2015-03-20.IonXpress_014.fastq |
reverse |
| 2015-03-20.IonXpress_015.fastq |
reverse |
Create a new folder and move the expected files to that directory (i.e., IonXpress_001 to IonXpress_015). There will be other files in the directory containing reads not mapped back to a sample by forward/reverse barcode combination (i.e., IonXpress_075). Our new directory is called 2014ION
2) Prepare Barcodes for each File
To simplify the demultiplexing process, we moved the 10 bp reverse barcodes to the front, just after the forward barcode, to create a new 20 bp unique ‘barcode’ for each sequence. For example:
cd forward
#Note that the 10bp forward barcode changes in each command correspond to each file
#The command searches the fastq file and moves the last 10bp to just after the forward barcode for each read
sed '2~4s/\(.*\)\(.\{10\}\)$/GTTACCTTAG\2\1/;' < 2015-03-20.IonXpress_001.fastq > F01_barcodes.fastq
sed '2~4s/\(.*\)\(.\{10\}\)$/GTTCTCCTTA\2\1/;' < 2015-03-20.IonXpress_002.fastq > F02_barcodes.fastq
sed '2~4s/\(.*\)\(.\{10\}\)$/GAATCCTCTT\2\1/;' < 2015-03-20.IonXpress_003.fastq > F03_barcodes.fastq
sed '2~4s/\(.*\)\(.\{10\}\)$/GATCTTGGTA\2\1/;' < 2015-03-20.IonXpress_004.fastq > F04_barcodes.fastq
sed '2~4s/\(.*\)\(.\{10\}\)$/GTTCCTTCTG\2\1/;' < 2015-03-20.IonXpress_005.fastq > F05_barcodes.fastq
sed '2~4s/\(.*\)\(.\{10\}\)$/GAACTTGCAG\2\1/;' < 2015-03-20.IonXpress_006.fastq > F06_barcodes.fastq
sed '2~4s/\(.*\)\(.\{10\}\)$/GAATCACGAA\2\1/;' < 2015-03-20.IonXpress_007.fastq > F07_barcodes.fastq
sed '2~4s/\(.*\)\(.\{10\}\)$/GTTATCGGAA\2\1/;' < 2015-03-20.IonXpress_008.fastq > F08_barcodes.fastq
sed '2~4s/\(.*\)\(.\{10\}\)$/GTTCCGCTCA\2\1/;' < 2015-03-20.IonXpress_009.fastq > F09_barcodes.fastq
sed '2~4s/\(.*\)\(.\{10\}\)$/GTTCGGTCAG\2\1/;' < 2015-03-20.IonXpress_010.fastq > F10_barcodes.fastq
3) Concatenate Forward FASTQ files
All sequences still have forward and reverse barcodes attached, in a new unique 20 bp forward barcode, so there is no chance of mixing up sequences by host sample.
cat *_barcodes.fastq > forwardseqs.fastq
4) Convert FASTQ to FASTA
This will created 2 new files in the forward directory: forwardseqs.fna and forwardseqs.qual. These are the new FASTA file (.fna) and the associated quality file (QUAL).
5) Validate Mapping File
We validate the mapping file that tells QIIME which which barcodes and primers belong to each sample so that we can maintain the path from sequences back to host samples. Make sure the SampleMapF.txt file is in the forward directory.
cd .. #change back to 2014ION dir
validate_mapping_file.py -m SampleMapF.txt
head SampleMapF.txt
The mapping file should look like this. Notice the new 20 bp barcode created in step 2) and the Ion-specific GAT adapter on the reverse primer:
6) Demultiplex and Quality Filter
During this step, we quality filter base calls less than Q20 and sequences less than 200 bp, assign QIIME labels to each sequence, corresponding to host sample, and then remove the new 20 bp barcode and both primers. These parameters can be changed with the -s (min_qual_score) and -l (min_seq_length) options. We also remove any sequences with a homopolymer run of 10 or more bp; there is a natural 8 bp conserved region in our target area. The expected length at this point is 234 bp.
split_libraries.py -m SampleMapF.txt -f ./forward/forwardseqs.fna -q ./forward/forwardseqs.qual -o demultiplexedF -b 20 -H 10 -M 1 -s 20 -z truncate_remove #took 1 min, 7 sec with test set
This step can take a while to run, so one can make sure QIIME is not hung up by occasionally going into the newly created directory and right clicking on the output file to check file size and make sure it grows between checks. The process is done when the cursor prompt returns to the terminal window.
7) Repeat steps 2–6 for Reverse FASTQ files
Note that a separate mapping file is needed with primer sequences also reverse complemented: SampleMapR.txt.
cd ./reverse
sed '2~4s/\(.*\)\(.\{10\}\)$/GATTCGAGGA\2\1/;' < 2015-03-20.IonXpress_011.fastq > R11_barcodes.fastq
sed '2~4s/\(.*\)\(.\{10\}\)$/GAACCACCTA\2\1/;' < 2015-03-20.IonXpress_012.fastq > R12_barcodes.fastq
sed '2~4s/\(.*\)\(.\{10\}\)$/GTCCGTTAGA\2\1/;' < 2015-03-20.IonXpress_013.fastq > R13_barcodes.fastq
sed '2~4s/\(.*\)\(.\{10\}\)$/GACACTCCAA\2\1/;' < 2015-03-20.IonXpress_014.fastq > R14_barcodes.fastq
sed '2~4s/\(.*\)\(.\{10\}\)$/GACCTCTAGA\2\1/;' < 2015-03-20.IonXpress_015.fastq > R15_barcodes.fastq
cat *_barcodes.fastq > reverseseqs.fastq
convert_fastaqual_fastq.py -f reverseseqs.fastq -c fastq_to_fastaqual
#creates 2 new files: reverseseqs.fna and reverseseqs.qual
cd ..
validate_mapping_file.py -m SampleMapR.txt
split_libraries.py -m SampleMapR.txt -f ./reverse/reverseseqs.fna -q ./reverse/reverseseqs.qual -o demultiplexedR -b 20 -H 10 -M 1 -s 20 -z truncate_remove #if you get a high number of mismatches and sequences are discarded, double check that you have the right mapping file
This step can take a while to run, so one can make sure QIIME is not hung up by occasionally going into the newly created directory and right clicking on the output file to check file size and make sure it grows between checks. The process is done when the cursor prompt returns to the terminal window.
8) Concatenate Forward and Reverse to 1 File
First we rename the forward FASTA file (containing all the forward sequences now) and move it to our main project folder. Repeat for the reverse FASTA file, reverse complement, and then concatenate all sequences into a single file with everything in the 5’ –> 3’ orientation.
We reverse complement the sequences using the FASTX Toolkit, which must be installed in our QIIME Virtual Box or directly in Macqiime or Linux in the main working directory. We used a local copy of FASTX Toolkit 0.0.12. Reverse complementing can also be done with the QIIME adjust_seq_orientation.py script. We used the FASTX command because we will use another FASTX tool later in this section.
cd demultiplexedF
mv seqs.fna Fseqs.fna
mv Fseqs.fna ..
cd ..
cd ./demultiplexedR
mv seqs.fna Rseqs.fna
mv Rseqs.fna ..
cd ..
fastx_reverse_complement -i ./Rseqs.fna -o ./Rseqs_flipped.fna
cat Fseqs.fna Rseqs_flipped.fna > 2014ionseqs.fna
9) Cluster Similar Sequences
Next we cluster similar sequences using the local alignment ‘swarm’ method and allowing only a 2 bp mismatch.
Mahé F, Rognes T, Quince C, de Vargas C, Dunthorn M. (2014) Swarm: robust and fast clustering method for amplicon-based studies. PeerJ 2:e593 http://dx.doi.org/10.7717/peerj.593
pick_otus.py -i ./2014ionseqs.fna -m swarm --swarm_resolution 2 -o ./swarmOTUs #took 1.8 sec with test set
Now we have a new directory with the clusters of sequences: swarmOTUs
This step can take a while to run, and no files are produced until the process is complete. So one can make sure QIIME is not hung up by using the top UNIX command in a new terminal window. The pick-otus QIIME command should be at the top of the list and using the greatest %CPU.
10) Build and Filter OTU Occurrence Table (BIOM)
We filtered out low abundance OTU clusters (< 10 copies in at least 1 sample of the entire data set) before writing data to the table using a script that calls the ‘pandas’ python package. We used Python 2.7.3 that should come as a dependency with the QIIME install. The provided ‘pandas_filter10.py’ script has to be in the swarmOTUs directory.
cd ./swarmOTUs #change to the new directory
cp ../pandas_filter10.py .
python pandas_filter10.py #This script will find the seqs.biom file created as output in the last step
This scipt creates a new file called exclude.txt that we can use in the next step to remove those low abundance OTU clusters.
The last command in UNIX will convert our final FASTA file to a tab-delimited file we can use to assign taxonomy in the BOLD database. This file will be useful when resolving taxonomic discrepancies in the last section: Manual Vetting. The fasta_formatter command is part of the FASTX Toolkit. We run the command and then manually add column headers to the text file called: seqID and seqs.
fasta_formatter -i ./2014ion_final_no_singletons.fna -o ./2014iontabseqs.txt -t
Assign Taxonomy and Filter Results – Run commands in R
After transferring the 2014tabseqs.txt and the 2014_biom_no_singletons.txt files to a working directory outside of the QIIME system, we used several R packages to assign taxonomy and filter out unwanted returns, such as low similarity matches and those outside a reasonable geographic area.
The following sections use the output files from the Illumina Miseq section above. If you only have output from the Ion Torrent section, use 2014iontabseqs.txt and 2014_ion_biom_no_singletons.txt
1) RStudio and R Notebooks
We used RStudio Version 1.0.136 – © 2009-2016 RStudio, Inc. Program R must first be installed on the same machine: https://www.r-project.org/. We used R version 3.3.2 (2016-10-31) – “Sincere Pumpkin Patch”. All remaining data processing steps in this section should be run in RStudio.
install.packages('rmarkdown')
library ('rmarkdown')
2) Set Working Directory and Read in Data
Change directory path as needed.
setwd("C:\\Users\\Owner\\Google Drive\\IONvsMISEQ")
mydata <- read.table("2014iontabseqs.txt", header = TRUE, sep = "\t", dec = ".", stringsAsFactors = FALSE)
head(mydata)
mydata2 <- as.list(setNames(mydata$seqs, mydata$seqID)) #make sure headers are not capitalized
3) Query BOLD for OTU Matches
Use the bold_identify function to get sequences from the BOLD API. This will return all the matches in BOLD, which should also include sequences mined from GenBank (https://www.ncbi.nlm.nih.gov/genbank/).
setwd("C:\\Users\\Owner\\Google Drive\\IONvsMISEQ")
mydata <- read.table("2014iontabseqs.txt", header = TRUE, sep = "\t", dec = ".", stringsAsFactors = FALSE)
head(mydata)
mydata2 <- as.list(setNames(mydata$seqs, mydata$seqID)) #make sure headers are not capitalized
4) Trim Output by User-specific Number of Matches
We trimmed our output to the top 40 matches for each OTU; this number can vary depending on project objectives. In many cases there will be up to 100 matches for each OTU. Results mined from GenBank are only returned at the Order level and require further investigation in the [Manual Vetting of Results] section. For our data, trimming to the 40 top matches left enough sequences to resolve discrepancies while also removing extranneous results, ultimately making it easier to parse through each OTU and assign taxonomy.
outtax40 <- lapply(output, head, n=40)
outtaxframe <- do.call("rbind", lapply(outtax40, data.frame))
The outtaxframe returns the top 40 matches, by similarity, from the BOLD results.
5) Filter out Seqs < 98% and Unlikely by Geography
This step not only filters out low percent similarity matches, but also helps with discrepancy resolution when several specimens from BOLD match one OTU at the same similarity.
We only kept matches that were > 98.4% but other studies have used lower % similarities. Without this filtering step it takes much longer to assign taxonomy with manual vetting of matches by geographic area. For example, even at > 98.4% similarity, it is possible for one OTU to match a moth specimen from the USA and a butterfly from Papua New Guinea.
#We used a custom header style for the final xlsx file
HS <- createStyle(fontSize=13, fontColour='navy', numFmt='GENERAL', halign='center', valign='center', textDecoration='bold', wrapText=TRUE)
install.packages('openxlsx')
install.packages('dplyr')
library(openxlsx) #Must have Rtools installed and check box to edit PATH or afterwards do: Sys.setenv("R_ZIPCMD" = "C:/Rtools/bin/zip.exe") ##path to zip.exe
library(dplyr)
library(tibble)
outtaxframe %<>% #This only keeps rows that we want and updates the dataframe
rownames_to_column("seqID") %>%
filter(specimen_country %in% c("United States", "Canada"), similarity >= 0.98)
write.xlsx(outtaxframe, file='2014outtaxframe40.xlsx', asTable=FALSE, colNames=TRUE, rowNames=TRUE, headerStyle=HS)
#Might get an error if Rtools is not installed - follow error message suggestions to get Rtools
The final filtered file should look like this, with up to 40 records for each denovo OTU:
Manual Vetting of Results – Work in a Web Browser
The 3 files of interest for assigning final taxonomy are: 2014outtaxframe40.xlsx, 2014tabseqs.txt, and 2014final_no_singletons.txt.
First, we open the 2014biom_no_singletons.txt file and convert any within-sample occurrences < 10 to 0 to remove low abundance OTU occurrences with simple find and replace commands in MS Excel. This step is to remove potential sequencing errors; the threshold of 10 is arbitrary and can be changed depending on project objectives.
Next, we open 2014outtaxframe40.xlsx and , and look for any discrepancies at the same similarity in our output from bold_identify, and then assign taxonomy in new columns in the 2014final_no_singletons.txt file.
Updating the BIOM table with Taxonomy
Sometimes there are discrepancies in the results returned from bold_identify that we need to manually investigate.
In this example, results for OTU denovo118 match 6 different species in the same genus at 100%. We know that all of these matching specimen records could occur within our region because we filtered the 2014outtaxframe40.xlsx based on similarity and geography. Nonetheless, we chose a simple example to demonstrate the process of how we learned to convert results into assigned taxonomy.
Discrepancy Example
Next, we go to our 2014tabseqs.txt file to find the sequence for denovo118
Find the Sequence in Question
Paste Sequence into BOLD
We get many matches at 100%, including some out of our area. There are several Catocala spp., as expected. We don’t expect any Nymphalidae butterflies in bat feces so we disregard those. That leaves Piletocera sodalis as another potential prey.
Re-examine the Matches
When we investigate Piletocera sodalis in the BOLD Taxonomy browser, we learn that it is only found in Japan, China, and Korea, so we disregard that potential prey. Because we still have 6 Catocala spp. possible, we can only assign taxonomy to OTU denovo118 as Catocala spp.
Cross-reference with Expectations
LS0tDQp0aXRsZTogIkJhdCBEaWV0IHZpYSBETkEgTWV0YWJhcmNvZGluZyAtLSBJbGx1bWluYSBNaVNlcSBhbmQgSW9uIFRvcnJlbnQgUEdNIg0KYXV0aG9yOiAiVGltb3RoeSBKIERpdm9sbCINCmRhdGU6ICIyNyBGZWJydWFyeSwgMjAxNyINCm91dHB1dDoNCiAgaHRtbF9kb2N1bWVudDoNCiAgICBjc3M6IH4vUi93aW4tbGlicmFyeS8zLjMvbWFya2Rvd24vcmVzb3VyY2VzL2thYmxlLmNzcw0KICAgIGhpZ2hsaWdodDogaGFkZG9jaw0KICAgIHNlbGZfY29udGFpbmVkOiBubw0KICAgIHRoZW1lOiBjb3Ntbw0KICAgIHRvYzogeWVzDQogIGh0bWxfbm90ZWJvb2s6DQogICAgY3NzOiB+L1Ivd2luLWxpYnJhcnkvMy4zL21hcmtkb3duL3Jlc291cmNlcy9rYWJsZS5jc3MNCiAgICBoaWdobGlnaHQ6IGhhZGRvY2sNCiAgICBzZWxmX2NvbnRhaW5lZDogeWVzDQogICAgdGhlbWU6IGNvc21vDQogICAgdG9jOiB5ZXMNCiAgcGRmX2RvY3VtZW50Og0KICAgIHRvYzogeWVzDQogIHdvcmRfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCnN1YnRpdGxlOiBTdXBwb3J0aW5nIEluZm9ybWF0aW9uIGZvciBtcyBpbiBNb2xlY3VsYXIgRWNvbG9neSBSZXNvdXJjZXMgLS0gQ29tcGFyaW5nDQogIHByZXkgRE5BIHJlY292ZXJ5IGZyb20gYmF0IGZlY2FsIHNhbXBsZXMgc2VxdWVuY2VkIG9uIHR3byBkaWZmZXJlbnQgc2Vjb25kLWdlbmVyYXRpb24NCiAgcGxhdGZvcm1zDQotLS0NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobz1UUlVFLCBldmFsPUZBTFNFLCBtZXNzYWdlPUZBTFNFKQ0KYGBgIA0KPGJyPg0KDQojPGEgaWQ9Ikluc3RhbGwiPjwvYT5JbnN0YWxsIGFuZCBTZXR1cA0KDQojIyMjVGhpcyB0dXRvcmlhbCBwcm92aWRlcyBndWlkYW5jZSBvbiBob3cgdG8gdHJhbnNmb3JtIHJhdyBJb24gVG9ycmVudCAqKm9yKiogSWxsdW1pbmEgTWlTZXEgYW1wbGljb24gZGF0YSBpbnRvIE9UVXMgZm9yIHRheG9ub21pYyBhc3NpZ25tZW50LiBUaGUgd29ya2Zsb3cgaW5jbHVkZXMgVU5JWCBjb21tYW5kcyB0byBjYWxsIFFJSU1FIChodHRwOi8vcWlpbWUub3JnLykgYW5kIEZBU1RYIFRvb2xraXQgKGh0dHA6Ly9oYW5ub25sYWIuY3NobC5lZHUvZmFzdHhfdG9vbGtpdC9kb3dubG9hZC5odG1sKSBzY3JpcHRzIHRvIHF1YWxpdHkgZmlsdGVyIGFuZCBjbHVzdGVyIHNlcXVlbmNlcyBiZWZvcmUgdXNpbmcgUHl0aG9uIHNjcmlwdHMgYW5kIFIgcGFja2FnZXMgdG8gZmlsdGVyIGFuZCBjbGVhbiBkYXRhIGZvciB0YXhvbm9taWMgYXNzaWdubWVudC4NCg0KIyMjI1dlIHJlY29tbWVuZCBmaXJzdCBydW5uaW5nIHRocm91Z2ggdGhlIGVudGlyZSBwcm9jZXNzIG91dGxpbmVkIGluIHRoaXMgZG9jdW1lbnQgd2l0aCB0aGUgcHJvdmlkZWQgdGVzdCBkYXRhIHNldHMgdG8gbWFrZSBzdXJlIGFsbCBzb2Z0d2FyZSBpcyBpbnN0YWxsZWQgcHJvcGVybHkgdW5kZXIgcmVkdWNlZCBwcm9jZXNzaW5nIGxvYWRzIChpLmUuLCBvbmx5IGEgY291cGxlIHNhbXBsZXMpLiBNYXRlcmlhbHMgYXJlIGF2YWlsYWJsZSBoZXJlOiBodHRwczovL2dpdGh1Yi5jb20vdGRpdm9sbC9CYXQtRGlldC1NZXRhYmFyY29kaW5nDQoNCiMjIyNUaGUgZmlyc3Qgc2VjdGlvbiBtdXN0IGJlIHBlcmZvcm1lZCBpbiBVTklYIChodHRwOi8vb3Blbmdyb3VwLm9yZy91bml4KSwgTWFjcWlpbWUgKGh0dHA6Ly93d3cud2VybmVybGFiLm9yZy9zb2Z0d2FyZS9tYWNxaWltZSksIG9yIHRocm91Z2ggYSBWaXJ0dWFsIE1hY2hpbmUgcnVubmluZyBVTklYLCBhcyBvdXRsaW5lZCBoZXJlOiAoaHR0cDovL3FpaW1lLm9yZy9pbnN0YWxsL3ZpcnR1YWxfYm94Lmh0bWwpLiBXZSB1c2VkIHRoZSByZWNvbW1lbmRlZCBRSUlNRSBWaXJ0dWFsIEJveCBpbnN0YWxsIG9uIGEgV2luZG93cyBtYWNoaW5lIHdpdGggMTZHQiBSQU0gYW5kIE9yYWNsZSBWaXJ0dWFsIEJveCBWZXJzaW9uIDUuMC44IHIxMDM0NDkgKGh0dHBzOi8vd3d3LnZpcnR1YWxib3gub3JnL3dpa2kvRG93bmxvYWRzKS4gDQoNCiMjIyNJbiB0aGUgUUlJTUUgVkIgU3lzdGVtIFNldHRpbmdzLCB3ZSBjaGFuZ2VkIGRlZmF1bHQgc2V0dGluZ3MgdG8gYWxsb3cgNCBjb3JlcyBhbmQgMTEgR0Igb2YgdmlydHVhbCBtZW1vcnkuDQoNCiMjIypWaXJ0dWFsIEJveCBTZXR0aW5ncyoNCiFbXShDOlxcVXNlcnNcXE93bmVyXFxHb29nbGUgRHJpdmVcXElPTnZzTUlTRVFcXEJhdERpZXRXb3JrZmxvd19maWxlc1xcVkJNYWluLmpwZykgDQoNCjxicj4NCg0KIyMjKlZpcnR1YWwgQm94IFByb2Nlc3NvciBDb3JlcyoNCiFbXShDOlxcVXNlcnNcXE93bmVyXFxHb29nbGUgRHJpdmVcXElPTnZzTUlTRVFcXEJhdERpZXRXb3JrZmxvd19maWxlc1xcVkJDb3Jlcy5qcGcpIA0KDQo8YnI+DQoNCiMjIypWaXJ0dWFsIEJveCBNZW1vcnkqDQohW10oQzpcXFVzZXJzXFxPd25lclxcR29vZ2xlIERyaXZlXFxJT052c01JU0VRXFxCYXREaWV0V29ya2Zsb3dfZmlsZXNcXFZCTWVtLmpwZykgDQoNCjxicj4NCg0KIyMjI0lmIHlvdSB3aWxsIGJlIHVzaW5nIGEgc2ltaWxhciB3b3JrZmxvdyBtb3JlIHRoYW4gb25jZSwgaXQgaGVscHMgdG8gdXNlIHRoZSAqKmB0aW1lYCoqIFVOSVggY29tbWFuZCBpbiBmcm9udCBvZiBvdGhlciBjb21tYW5kcy4gVGhpcyBjb21tYW5kIHJldHVybnMgdGhlIHByb2Nlc3NpbmcgdGltZSwgaW4gbWludXRlcyBhbmQgc2Vjb25kcywgd2hpY2ggc2ltcGx5IGhlbHBzIHBsYW4gZnV0dXJlIGRhdGEgYW5hbHlzZXMuIEZvciBleGFtcGxlOg0KIVtdKEM6XFxVc2Vyc1xcT3duZXJcXEdvb2dsZSBEcml2ZVxcSU9OdnNNSVNFUVxcQmF0RGlldFdvcmtmbG93X2ZpbGVzXFx0aW1lRXguanBnKQ0KDQo8YnI+DQoNCiM8YSBpZD0iSWxsdW1pbmEgTWlTZXEiPjwvYT5JbGx1bWluYSBNaVNlcSBXb3JrZmxvdyAtLSBfX19SdW4gY29tbWFuZHMgaW4gVU5JWF9fXyANCjxicj4NCg0KIyMjIyBJZiB5b3Ugb25seSBoYXZlIElvblRvcnJlbnQgZGF0YSwgc2tpcCB0aGUgW0lsbHVtaW5hIE1pU2VxXSBzZWN0aW9uIGFuZCBnbyB0byB0aGUgW0lvbiBUb3JyZW50XSgjSW9uIFRvcnJlbnQpIHNlY3Rpb24NCg0KIyMjI0FsbCBjb21tYW5kcyBpbiB0aGlzIHNlY3Rpb24gd2VyZSBydW4gaW5zaWRlIHRoZSBRSUlNRSBWaXJ0dWFsIEJveCBjcmVhdGVkIGFib3ZlIGluIHRoZSBbSW5zdGFsbF0oI0luc3RhbGwpIHNlY3Rpb24NCjxicj4NCg0KIyMjICoqMSkqKiBPcmdhbml6ZSBSMSBhbmQgUjIgRmlsZXMNCiMjIyNGaXJzdCBsb2FkIGFsbCBjb21wcmVzc2VkIFIxIGFuZCBSMiAqLmZhc3RxLmd6IHBhaXJlZCBmaWxlcyBpbnRvIGEgbmV3IGZvbGRlciwgc3VjaCBhczogKipgMjAxNE1JU0VRYCoqDQojIyMjRHJhZyBhbmQgZHJvcCBmcm9tIFdpbmRvd3MgdG8gVmlydHVhbCBCb3ggb3IgdXNlICoqYG12YCoqIGlmIHdvcmtpbmcgZGlyZWN0bHkgaW4gVU5JWCBvciBNYWNxaWltZSANCjxicj4NCmBgYHtyLCBlbmdpbmU9ImJhc2giLCBlY2hvPVRSVUV9DQpta2RpciAyMDE0TUlTRVEgICANCmBgYA0KDQojIyMjIFFJSU1FIHdpbGwgbm90IGFjY2VwdCB1bmRlcnNjb3JlcyBvciBoeXBoZW5zIGluIFNhbXBsZSBJRHMgdXNlZCBpbiB0aGUgUUlJTUUgcHJvY2VzcywgdGh1cywgeW91IG1heSBoYXZlIHRvIHJlbmFtZSBmb2xkZXIgbmFtZXMgc28gdGhlcmUgYXJlIG5vIHVuZGVyc2NvcmVzIGJlZm9yZSBMMDAxOyBjaGFuZ2UgdW5kZXJzY29yZXMgYW5kIGh5cGhlbnMgdG8gcGVyaW9kcywgZXhjZXB0IGFmdGVyIEwwMDEuIEV2ZXJ5dGhpbmcgYmVmb3JlIEwwMDEgd2lsbCBiZWNvbWUgdGhlIFNhbXBsZSBJRC4gQW4gZXhhbXBsZSBvZiBiYXNoIGNvZGUgdG8gZG8gdGhpcyBmb2xsb3dzOg0KYGBge3IsIGZpeGZpbGVuYW1lcy5zaCwgZW5naW5lPSJiYXNoIiwgZWNobz1UUlVFfQ0KIyEvYmluL2Jhc2ggICAjc2F2ZSB0aGlzIGFzIGEgc2NyaXB0IGNhbGxlZCBmaXhmaWxlbmFtZXMuc2ggYW5kIHNhdmUgaW4geW91ciBQcm9qZWN0IGZvbGRlcg0KY2QgJDE7DQpmb3IgZmlsZSBpbiAqTDAwMSo7IGRvDQogIGZwID0gIiR7ZmlsZSVMMDAxKn0iOw0KICBscCA9ICIke2ZpbGUjKkwwMDF9IjsNCiAgbmV3ID0gIiR7ZnAvL18vLn1MMDAxJGxwIjsNCiAgbXYgIiRmaWxlIiAiJG5ldyI7DQpkb25lDQpgYGANCiMjIyMgTm93IGNoYW5nZSBwZXJtaXNzaW9ucyBhbmQgcnVuIHRoZSBzY3JpcHQuDQpgYGB7ciwgZW5naW5lPSJiYXNoIiwgZWNobz1UUlVFfQ0KY2QgMjAxNE1JU0VRDQoNCmNobW9kIHUreCBmaXhmaWxlbmFtZXMuc2gNCg0KLi9maXhmaWxlbmFtZXMuc2gNCmBgYA0KDQo8YnI+DQoNCiMjIyAqKjIpKiogSm9pbmVkIFBhaXJlZCBFbmRzDQojIyMjTmV4dCwgd2Ugam9pbiBjb3JyZXNwb25kaW5nIHBhaXJlZCByZWFkcyAqKl8oUjEgYW5kIFIyKV8qKiBmb3IgZWFjaCBzYW1wbGUgdG8gaW5jcmVhc2UgcmVhZCBxdWFsaXR5IGFuZCBwcm9wYWdhdGUgdGhhdCBxdWFsaXR5IG9uIHRocm91Z2ggdG8gdGF4b25vbWljIGFzc2lnbm1lbnQuDQoNCmBgYGB7ciwgZW5naW5lPSJiYXNoIiwgZWNobz1UUlVFfQ0KbXVsdGlwbGVfam9pbl9wYWlyZWRfZW5kcy5weSAtaSAvaG9tZS9xaWltZS8yMDE0TUlTRVEgLW8gL2hvbWUvcWlpbWUvMjAxNE1JU0VRL2pvaW5lZF9zZXFzDQojdG9vayAxMCBzZWNzIHdpdGggdGVzdCBzZXQNCmBgYGANCg0KIyMjIyBXZSBvdXRwdXQgdGhlIGpvaW5lZCBzZXF1ZW5jZSBmaWxlcywgMSBwZXIgYmF0IHNhbXBsZSwgaW50byBhIG5ldyBkaXJlY3RvcnkgY2FsbGVkOiAqKmBqb2luZWRfc2Vxc2AqKg0KDQojIyMjTm93IHdlIHRha2Ugb3V0IHRoZSAqKnVuam9pbmVkIHNlcXVlbmNlcyoqIHNvIHRoZXkgZG8gbm90IGdldCBtaXhlZCB1cCBpbiBkb3duc3RyZWFtIGFuYWx5c2VzLiBZb3UgbWF5IHByZWZlciB0byBzYXZlIHRoZXNlIHNvbWV3aGVyZSBpZiB0aGV5IGNvdWxkIGJlIHVzZWZ1bCB0byB5b3VyIHBhcnRpY3VsYXIgYXBwbGljYXRpb24uDQoNCmBgYHtyLCBlbmdpbmU9ImJhc2giLCBlY2hvPVRSVUV9DQpjZCBqb2luZWRfc2VxcyAgICAgI2NoYW5nZSBkaXJlY3RvcnkgdG8gdGhlIG5ld2x5IGNyZWF0ZWQgam9pbmVkX3NlcXMgZGlyZWN0b3J5DQoNCmZpbmQgLiAtbmFtZSAiKi51bjEuZmFzdHEiIC10eXBlIGYgLWRlbGV0ZSAgICAgI2RvIHRoaXMgZXhhY3RseSBhcyB3cml0dGVuIHRvIGF2b2lkIGRlbGV0aW5nIG90aGVyIGZpbGVzDQoNCmZpbmQgLiAtbmFtZSAiKi51bjIuZmFzdHEiIC10eXBlIGYgLWRlbGV0ZQ0KYGBgDQo8YnI+DQoNCiMjIyAqKjMpKiogUXVhbGl0eSBGaWx0ZXIgYW5kIEFzc2lnbiBTYW1wbGUgSURzIHRvIFNlcXVlbmNlcw0KIyMjI0lsbHVtaW5hIE1pU2VxIHBsYXRmb3JtIHRyaW1zIE5leHRlcmEgaW5kaWNlcyBhbmQgYWRhcHRvcnMgcHJpb3IgdG8gd3JpdGluZyBzZXF1ZW5jZSBkYXRhIHRvIEJhc2VTcGFjZS4gSG93ZXZlciwgd2Ugc3RpbGwgdXNlIFFJSU1FJ3Mgc3BsaXRfbGlicmFyaWVzIHNjcmlwdCB0byBhc3NpZ24gU2FtcGxlIElEcyB0byBlYWNoIGluZGl2aWR1YWwgc2VxdWVuY2UgdXNpbmcgZm9sZGVyIG5hbWVzIGFuZCBjb25jYXRlbmF0ZSBhbGwgam9pbmVkIHNlcXVlbmNlcyBpbnRvIG9uZSBmaWxlIGZvciBkb3duc3RyZWFtIGFuYWx5c2VzLg0KDQojIyMjRGVmYXVsdCBxdWFsaXR5IGZpbHRlcmluZyBwYXJhbWV0ZXJzIGFyZSBhcHBsaWVkIGhlcmUgc28gdGhhdCBiYXNlIGNhbGxzIGxlc3MgdGhhbiBRMjUgYW5kIHNlcXVlbmNlcyBsZXNzIHRoYW4gMjAwIGJwIGFyZSByZW1vdmVkLiBUaGVzZSBwYXJhbXRlcnMgY2FuIGJlIGNoYW5nZWQgd2l0aCB0aGUgKipgLXMgKG1pbl9xdWFsX3Njb3JlKWAqKiBhbmQgKipgLWwgKG1pbl9zZXFfbGVuZ3RoKWAqKiBvcHRpb25zLiBPdXIgZXhwZWN0ZWQgbGVuZ3RoIGF0IHRoaXMgc3RlcCBpcyAyMTEgYnAuDQoNCg0KYGBge3IsIGVuZ2luZT0iYmFzaCIsIGVjaG89VFJVRX0NCmNkIC4uICAgICAjY2hhbmdlIGRpcmVjdG9yeSBiYWNrIHRvIHRoZSBtYWluIHdvcmtpbmcgZGlyZWN0b3J5DQoNCm11bHRpcGxlX3NwbGl0X2xpYnJhcmllc19mYXN0cS5weSAtaSAvaG9tZS9xaWltZS8yMDE0TUlTRVEvam9pbmVkX3NlcXMgLW8gL2hvbWUvcWlpbWUvMjAxNE1JU0VRL3NwbGl0X291dCAtLWRlbXVsdGlwbGV4aW5nX21ldGhvZCBzYW1wbGVpZF9ieV9maWxlIC0taW5jbHVkZV9pbnB1dF9kaXJfcGF0aCAtLXJlbW92ZV9maWxlcGF0aF9pbl9uYW1lICAjdG9vayAxNiBzZWNzIHdpdGggdGVzdCBzZXQNCmBgYA0KIyMjIyBXZSBvdXRwdXQgdGhlIHJlc3VsdGluZyBGQVNUQSBmaWxlIChRSUlNRSB1c2VzIHRoZSBmaWxlIGV4dGVuc2lvbiAuZm5hKSBhbmQgbG9nIGZpbGVzIGludG8gYSBuZXcgZGlyZWN0b3J5IGNhbGxlZDogKipgc3BsaXRfb3V0YCoqDQoNCiMjIyMjKipUaGlzIHN0ZXAgY2FuIHRha2UgYSB3aGlsZSB0byBydW4sIHNvIG9uZSBjYW4gbWFrZSBzdXJlIFFJSU1FIGlzIG5vdCBodW5nIHVwIGJ5IG9jY2FzaW9uYWxseSBnb2luZyBpbnRvIHRoZSBuZXdseSBjcmVhdGVkIGRpcmVjdG9yeSBhbmQgcmlnaHQgY2xpY2tpbmcgb24gdGhlIG91dHB1dCBmaWxlIHRvIGNoZWNrIGZpbGUgc2l6ZSBhbmQgbWFrZSBzdXJlIGl0IGdyb3dzIGJldHdlZW4gY2hlY2tzLiBUaGUgcHJvY2VzcyBpcyBkb25lIHdoZW4gdGhlIGN1cnNvciBwcm9tcHQgcmV0dXJucyB0byB0aGUgdGVybWluYWwgd2luZG93LioqDQo8YnI+DQoNCiMjIyAqKjQpKiogVHJpbSBQcmltZXJzDQojIyMjIE5vdyB3ZSBuZWVkIHRvIHJlbW92ZSBaZWFsZSBwcmltZXJzIGZyb20gdGhlIDUnICoqYW5kKiogMycgZW5kcyBvZiBlYWNoIHNlcXVlbmNlLiBJdCBpcyBlYXNpZXN0IHRvIHJlbW92ZSB0aGUgcmV2ZXJzZSBwcmltZXIgZmlyc3QgZnJvbSB0aGUgMycgZW5kLCB0aGVuIHJldmVyc2UgY29tcGxlbWVudCB0aGUgc2VxdWVuY2VzLCByZW1vdmUgdGhlIGZvcndhcmQgcHJpbWVyIHdoaWNoIGlzIG5vdyBpbiBhIHJldmVyc2Ugb3JpZW50YXRpb24gb24gdGhlIDMnIGVuZCwgdGhlbiByZXZlcnNlIGNvbXBsZW1lbnQgdGhlIHNlcXVlbmNlcyBhZ2FpbiBzbyB0aGV5IGFyZSBiYWNrIGluIHRoZSA1JyAtLT4gMycgZGlyZWN0aW9uIHdpdGggYm90aCBwcmltZXJzIHJlbW92ZWQuDQoNCiMjIyNGaXJzdCB3ZSB2YWxpZGF0ZSB0aGUgbWFwcGluZyBmaWxlIHdoaWNoIHRlbGxzIFFJSU1FIHdoYXQgdGhlIHByaW1lciBzZXF1ZW5jZXMgc2hvdWxkIGJlLiANCiMjIyMgSWYgUUlJTUUgZmxhZ3MgYW55IGVycm9ycywgbWFrZSBjaGFuZ2VzIGFzIG5lY2Vzc2FyeTsgaGVscCBjYW4gYmUgZm91bmQgaGVyZTogaHR0cDovL3FpaW1lLm9yZy9zY3JpcHRzL3ZhbGlkYXRlX21hcHBpbmdfZmlsZS5odG1sDQo8YnI+DQoNCmBgYHtyLCBlbmdpbmU9ImJhc2giLCBlY2hvPVRSVUV9DQp2YWxpZGF0ZV9tYXBwaW5nX2ZpbGUucHkgLW0gU2FtcGxlTWFwRmlsZS50eHQgICNnb29kIHByYWN0aWNlIHRvIG1ha2Ugc3VyZSBhbGwgY29sdW1ucyBhcmUgaW4gY29ycmVjdCBmb3JtYXQNCg0KdHJ1bmNhdGVfcmV2ZXJzZV9wcmltZXIucHkgLWYgLi9zcGxpdF9vdXQvc2Vxcy5mbmEgLW0gLi9TYW1wbGVNYXBGaWxlLnR4dCAteiB0cnVuY2F0ZV9yZW1vdmUgLU0gMSAtbyAuL1J0cnVuY2F0ZWQNCmBgYA0KDQojIyMjIFRoZSAuZm5hIGZpbGUgaXMgb3VyIHNlcXVlbmNlIGZpbGUsIGFuZCB0aGUgU2FtcGxlTWFwRmlsZS50eHQgaXMgdGhlIG1hcHBpbmcgZmlsZSB3aXRoIGZvcndhcmQgYW5kIHJldmVyc2UgcHJpbWVyIHNlcXVlbmNlIGluZm8uIEluIHRoaXMgY2FzZSwgd2UgYWxsb3cgMSBtaXNtYXRjaCBpbiB0aGUgcHJpbWVyIHNlcXVlbmNlLiBUaGUgbWFwcGluZyBmaWxlIG11c3QgaGF2ZSB1bmlxdWUgYmFyY29kZXMgZm9yIGVhY2ggc2FtcGxlLiBCZWNhc3VlIHRoZSBiYXJjb2RlcyBhcmUgYWxyZWFkeSByZW1vdmVkIGJ5IElsbHVtaW5hLCB3ZSBzaW1wbHkgY29uY2F0ZW5hdGVkIGZvcndhcmQgYW5kIHJldmVyc2UgaW5kZXhlcyB1c2VkIGluIHRoZSBzZXF1ZW5jaW5nIHByb2Nlc3Mgc28gZWFjaCBzYW1wbGUgaGFzIGEgdW5pcXVlICdiYXJjb2RlJyB0byBzYXRpc2Z5IHRoZSBgdmFsaWRhdGVfbWFwcGluZ19maWxlLnB5YDoNCiFbXShDOlxcVXNlcnNcXE93bmVyXFxHb29nbGUgRHJpdmVcXElPTnZzTUlTRVFcXEJhdERpZXRXb3JrZmxvd19maWxlc1xcTWFwRXguanBnKQ0KDQojIyMjV2UgcmV2ZXJzZSBjb21wbGVtZW50IHRoZSBzZXF1ZW5jZXMgdXNpbmcgdGhlIEZBU1RYIFRvb2xraXQsIHdoaWNoIG11c3QgYmUgaW5zdGFsbGVkIGluIG91ciBRSUlNRSBWaXJ0dWFsIEJveCBvciBkaXJlY3RseSBpbiBNYWNxaWltZSBvciBMaW51eCBpbiB0aGUgbWFpbiB3b3JraW5nIGRpcmVjdG9yeSwgdGhlbiBhZ2FpbiByZW1vdmUgcmV2ZXJzZSBwcmltZXJzLCBhbmQgZmxpcCBzZXF1ZW5jZXMgYmFjay4gV2UgdXNlZCBhIGxvY2FsIGNvcHkgb2YgRkFTVFggVG9vbGtpdCAwLjAuMTIuIFJldmVyc2UgY29tcGxlbWVudGluZyBjYW4gYWxzbyBiZSBkb25lIHdpdGggdGhlIFFJSU1FICoqYGFkanVzdF9zZXFfb3JpZW50YXRpb24ucHlgKiogc2NyaXB0LiBXZSB1c2VkIHRoZSBGQVNUWCBjb21tYW5kIGJlY2F1c2Ugd2Ugd2lsbCB1c2UgYW5vdGhlciBGQVNUWCB0b29sIGxhdGVyIGluIHRoaXMgc2VjdGlvbi4NCjxicj4NCg0KIyMjIyMqKk5vdGUgdGhhdCBhIHNlcGFyYXRlIG1hcHBpbmcgZmlsZSBpcyBuZWVkZWQgd2l0aCBwcmltZXIgc2VxdWVuY2VzIGFsc28gcmV2ZXJzZSBjb21wbGVtZW50ZWQ6IGBTYW1wbGVNYXBGaWxlX3JldmVyc2UudHh0YC4qKg0KDQpgYGB7ciwgZW5naW5lPSJiYXNoIiwgZWNobz1UUlVFfQ0KZmFzdHhfcmV2ZXJzZV9jb21wbGVtZW50IC1pIC4vUnRydW5jYXRlZC9zZXFzX3Jldl9wcmltZXJfdHJ1bmNhdGVkLmZuYSAtbyAuL1Jjb21wDQoNCnRydW5jYXRlX3JldmVyc2VfcHJpbWVyLnB5IC1mIC4vUmNvbXAgLW0gLi9TYW1wbGVNYXBGaWxlX3JldmVyc2UudHh0IC16IHRydW5jYXRlX3JlbW92ZSAtTSAxIC1vIC4vUmNvbXBfZm9yd2FyZF9yZW1vdmVkDQoNCmZhc3R4X3JldmVyc2VfY29tcGxlbWVudCAtaSAuL1Jjb21wX2ZvcndhcmRfcmVtb3ZlZC9SY29tcF9yZXZfcHJpbWVyX3RydW5jYXRlZC5mbmEgLW8gLi90cmltbWVkX3NlcXMuZm5hDQpgYGANCiMjIyMgV2Ugbm93IGhhdmUgYSBmaWxlIGNhbGxlZCAqKmB0cmltbWVkX3NlcXMuZm5hYCoqIHdpdGggYWxsIHByaW1lcnMgcmVtb3ZlZC4NCjxicj4NCg0KIyMjICoqNSkqKiBDbHVzdGVyIFNpbWlsYXIgU2VxdWVuY2VzDQojIyMjTmV4dCB3ZSBjbHVzdGVyIHNpbWlsYXIgc2VxdWVuY2VzIHVzaW5nIHRoZSBsb2NhbCBhbGlnbm1uZXQgJ3N3YXJtJyBtZXRob2QgYW5kIGFsbG93aW5nIG9ubHkgYSAyIGJwIG1pc21hdGNoLg0KDQojIyMjIyNNYWjpIEYsIFJvZ25lcyBULCBRdWluY2UgQywgZGUgVmFyZ2FzIEMsIER1bnRob3JuIE0uICgyMDE0KSBTd2FybTogcm9idXN0IGFuZCBmYXN0IGNsdXN0ZXJpbmcgbWV0aG9kIGZvciBhbXBsaWNvbi1iYXNlZCBzdHVkaWVzLiBQZWVySiAyOmU1OTMgPGh0dHA6Ly9keC5kb2kub3JnLzEwLjc3MTcvcGVlcmouNTkzPg0KDQpgYGB7ciwgZW5naW5lPSJiYXNoIiwgZWNobz1UUlVFfQ0KcGlja19vdHVzLnB5IC1pIC4vdHJpbW1lZF9zZXFzLmZuYSAtbSBzd2FybSAtLXN3YXJtX3Jlc29sdXRpb24gMiAtbyAuL3N3YXJtT1RVcyAgICAjdG9vayAxOCBzZWMgd2l0aCB0ZXN0IHNldA0KYGBgDQojIyMjIE5vdyB3ZSBoYXZlIGEgbmV3IGRpcmVjdG9yeSB3aXRoIHRoZSBjbHVzdGVycyBvZiBzZXF1ZW5jZXM6ICoqYHN3YXJtT1RVc2AqKg0KDQojIyMjIyoqVGhpcyBzdGVwIGNhbiB0YWtlIGEgd2hpbGUgdG8gcnVuLCBhbmQgbm8gZmlsZXMgYXJlIHByb2R1Y2VkIHVudGlsIHRoZSBwcm9jZXNzIGlzIGNvbXBsZXRlLiBPbmUgY2FuIG1ha2Ugc3VyZSBRSUlNRSBpcyBub3QgaHVuZyB1cCBieSB1c2luZyB0aGUqKiAqKmB0b3BgKiogKipVTklYIGNvbW1hbmQgaW4gYSBuZXcgdGVybWluYWwgd2luZG93LiBUaGUgcGljay1vdHVzIFFJSU1FIGNvbW1hbmQgc2hvdWxkIG5vcm1hbGx5IGJlIGF0IHRoZSB0b3Agb2YgdGhlIGxpc3QgYW5kIHVzaW5nIHRoZSBncmVhdGVzdCAlQ1BVLioqDQoNCjxicj4NCg0KIyMjICoqNikqKiBCdWlsZCBhbmQgRmlsdGVyIE9UVSBPY2N1cnJlbmNlIFRhYmxlIChCSU9NKQ0KIyMjI1dlIG5vdyBjcmVhdGUgb3VyIEJJT00gdGFibGUgdG8ga2VlcCB0cmFjayBvZiB3aGljaCBPVFVzIHdlcmUgcHJlc2VudCBpbiBlYWNoIHNhbXBsZS4gV2UgdXNlIHRoZSBuZXcgc3dhcm0gb3V0cHV0IGZpbGUgKipgdHJpbW1lZF9zZXFzX290dXMudHh0YCoqIGFzIGlucHV0Lg0KYGBge3IsIGVuZ2luZT0iYmFzaCIsIGVjaG89VFJVRX0NCm1ha2Vfb3R1X3RhYmxlLnB5IC1pIC4vc3dhcm1PVFVzL3RyaW1tZWRfc2Vxc19vdHVzLnR4dCAtbyAuL3N3YXJtT1RVcy9zZXFzLmJpb20NCmBgYA0KDQpXZSBmaWx0ZXIgb3V0IGxvdyBhYnVuZGFuY2UgT1RVIGNsdXN0ZXJzICg8IDEwIGNvcGllcyBpbiBhdCBsZWFzdCAxIHNhbXBsZSBvZiB0aGUgZW50aXJlIGRhdGEgc2V0KSBiZWZvcmUgd3JpdGluZyBkYXRhIHRvIHRoZSB0YWJsZSB1c2luZyBhIHNjcmlwdCB0aGF0IGNhbGxzIHRoZSAncGFuZGFzJyBweXRob24gcGFja2FnZS4gV2UgdXNlZCBQeXRob24gMi43LjMgdGhhdCBzaG91bGQgY29tZSBhcyBhIGRlcGVuZGVuY3kgd2l0aCB0aGUgUUlJTUUgaW5zdGFsbC4gVGhlIHByb3ZpZGVkICdwYW5kYXNfZmlsdGVyMTAucHknIHNjcmlwdCBoYXMgdG8gYmUgaW4gdGhlICoqYHN3YXJtT1RVc2AqKiBkaXJlY3RvcnkuICANCg0KYGBge3IsIGVuZ2luZT0iYmFzaCIsIGVjaG89VFJVRX0NCmNkIC4vc3dhcm1PVFVzICAgICAjY2hhbmdlIHRvIHRoZSBuZXcgZGlyZWN0b3J5DQoNCmNwIC4uL3BhbmRhc19maWx0ZXIxMC5weSAuDQoNCnB5dGhvbiBwYW5kYXNfZmlsdGVyMTAucHkgICAgICNUaGlzIHNjcmlwdCB3aWxsIGZpbmQgdGhlIHNlcXMuYmlvbSBmaWxlIGNyZWF0ZWQgYXMgb3V0cHV0IGluIHRoZSBsYXN0IHN0ZXANCmBgYA0KIyMjI1RoaXMgc2NpcHQgY3JlYXRlcyBhIG5ldyBmaWxlIGNhbGxlZCAqKmBleGNsdWRlLnR4dGAqKiB0aGF0IHdlIGNhbiB1c2UgaW4gdGhlIG5leHQgc3RlcCB0byByZW1vdmUgdGhvc2UgbG93IGFidW5kYW5jZSBPVFUgY2x1c3RlcnMuICANCg0KIyMjI0FmdGVyIHJlbW92aW5nIHRoZSB1bndhbnRlZCBsb3cgYWJ1bmRhbmNlIE9UVSBjbHVzdGVycywgd2Ugd3JpdGUgdGhlIGRlc2lyZWQgT1RVcyB0byBhIEJJT00gdGFibGUgaW4gaHVtYW4tcmVhZGFibGUgdGFidWxhciBmb3JtYXQuIFRvIGxhYmVsIHRoZSBkZW5vdm8gT1RVcywgd2UgdXNlIHRoZSAqKmBwaWNrX3JlcF9zZXQucHlgKiogc2NyaXB0IHRvIHBpY2sgb25lIHJlcHJlc2VudGF0aXZlIHNlcXVlbmNlIGZyb20gZWFjaCBjbHVzdGVyLiBUaGVuIHdlIHB1bGwgdGhvc2UgZGVzaXJlZCByZXByZXNlbnRhdGl2ZSBzZXF1ZW5jZXMgZnJvbSBvdXIgb3JpZ2luYWwgLmZuYSBmaWxlIGFuZCB3cml0ZSBhIG5ldyAuZm5hLiBGcm9tIGhlcmUgb24gb3V0LCB3ZSB1c2UgdGhlIHJlcHJlc2VudGF0aXZlIHNlcXVlbmNlcyBmcm9tIGVhY2ggT1RVIGNsdXN0ZXIgdG8gcmVkdWNlIHByb2Nlc3NpbmcgZGVtYW5kLg0KDQpgYGB7ciwgZW5naW5lPSJiYXNoIiwgZWNobz1UUlVFfQ0KY2QgLi4gICAgICNjaGFuZ2UgYmFjayB0byB0aGUgbWFpbiB3b3JraW5nIGRpcmVjdG9yeQ0KDQpmaWx0ZXJfb3R1c19mcm9tX290dV90YWJsZS5weSAtaSAuL3N3YXJtT1RVcy9zZXFzLmJpb20gLW8gLi9zd2FybU9UVXMvb3R1X3RhYmxlX25vX3NpbmdsZXRvbnMuYmlvbSAtZSAuL3N3YXJtT1RVcy9leGNsdWRlLnR4dA0KDQpiaW9tIGNvbnZlcnQgLWkgLi9zd2FybU9UVXMvb3R1X3RhYmxlX25vX3NpbmdsZXRvbnMuYmlvbSAtbyAuL3N3YXJtT1RVcy8yMDE0X2Jpb21fbm9fc2luZ2xldG9ucy50eHQgLS10YWJsZS10eXBlPSJPVFUgdGFibGUiIC0tdG8tdHN2DQoNCnBpY2tfcmVwX3NldC5weSAtaSAuL3N3YXJtT1RVcy90cmltbWVkX3NlcXNfb3R1cy50eHQgLWYgLi90cmltbWVkX3NlcXMuZm5hIC1tIG1vc3RfYWJ1bmRhbnQgLW8gLi8yMDE0X2ZpbmFsLmZuYSAtbCAuLzIwMTRmaW5hbF9sb2cNCg0KZmlsdGVyX2Zhc3RhLnB5IC1mIC4vMjAxNF9maW5hbC5mbmEgLWIgLi9zd2FybU9UVXMvb3R1X3RhYmxlX25vX3NpbmdsZXRvbnMuYmlvbSAtbyAuLzIwMTRfZmluYWxfbm9fc2luZ2xldG9ucy5mbmENCmBgYA0KIyMjI1RoZSBsYXN0IGNvbW1hbmQgaW4gVU5JWCB3aWxsIGNvbnZlcnQgb3VyIGZpbmFsIEZBU1RBIGZpbGUgdG8gYSB0YWItZGVsaW1pdGVkIGZpbGUgd2UgY2FuIHVzZSB0byBhc3NpZ24gdGF4b25vbXkgaW4gdGhlIEJPTEQgZGF0YWJhc2UuIFRoaXMgZmlsZSB3aWxsIGJlIHVzZWZ1bCB3aGVuIHJlc29sdmluZyB0YXhvbm9taWMgZGlzY3JlcGFuY2llcyBpbiB0aGUgbGFzdCBzZWN0aW9uOiBbTWFudWFsIFZldHRpbmcgb2YgUmVzdWx0c10uIFRoZSAqKmBmYXN0YV9mb3JtYXR0ZXJgKiogY29tbWFuZCBpcyBwYXJ0IG9mIHRoZSBGQVNUWCBUb29sa2l0LiBXZSBydW4gdGhlIGNvbW1hbmQgYW5kIHRoZW4gbWFudWFsbHkgYWRkIGNvbHVtbiBoZWFkZXJzIHRvIHRoZSB0ZXh0IGZpbGUgY2FsbGVkOiAqKnNlcUlEKiogYW5kICoqc2VxcyoqLiAgICANCg0KYGBge3IsIGVuZ2luZT0iYmFzaCIsIGVjaG89VFJVRX0NCmZhc3RhX2Zvcm1hdHRlciAtaSAuLzIwMTRfZmluYWxfbm9fc2luZ2xldG9ucy5mbmEgLW8gLi8yMDE0dGFic2Vxcy50eHQgLXQNCmBgYA0KDQojIyMjVGhlIGZpbmFsICoqYDIwMTR0YWJzZXFzLnR4dGAqKiBmaWxlIHdpbGwgbG9vayBsaWtlIHRoaXM6DQoNCg0KfCAqKnNlcUlEKiogICAgICAgfCAqKnNlcXMqKiAgfA0KfDotLS0tLS0tLS0tLS0tLS0tfDotLS0tLS0tLS06fA0KfCBkZW5vdm8wIEYxMFIxMl8yIHwgICAgIEFBVFRUR0FHQ0FHIC4gLiAuIC4gLiB8DQp8IGRlbm92bzEgRjEwUjEyXzExMjEgfCAgICAgQUFUVFRHQUdDQUdHIC4gLiAuIC4gLiB8DQp8IGRlbm92bzEwIEYxUjEzXzE2Njg0MSB8ICAgICBBQUdBVEdBR0NUR0cgLiAuIC4gLiAuIHwNCnwgLiAuIC4gLiAuIC4gLiAuIC4gfCAgICAgLiAuIC4gLiAuIHwNCnwgZGVub3ZvNzg5IEYxMFI1XzI0ODIgfCAgICAgQUFHQVRHQ0NUR0dBQSAuIC4gLiAuIC4gfA0KDQojIyMjIElmIHlvdSBvbmx5IGhhdmUgSWxsdW1pbmEgZGF0YSwgc2tpcCB0aGUgW0lvbiBUb3JyZW50XSgjSW9uIFRvcnJlbnQpIHNlY3Rpb24gYW5kIGdvIHRvIHRoZSBbQXNzaWduIFRheG9ub215XSgjQXNzaWduIFRheG9ub215KSBzZWN0aW9uDQo8YnI+DQoNCiM8YSBpZD0iSW9uIFRvcnJlbnQiPjwvYT5Jb24gVG9ycmVudCBQR00gV29ya2Zsb3cgLS0gX19fUnVuIGNvbW1hbmRzIGluIFVOSVhfX18NCg0KIyMjI1RoZSBJb24gVG9ycmVudCBQZXJzb25hbCBHZW5vbWUgTWFjaGluZSAoUEdNKSBpcyB3aWRlbHkgdXNlZCBmb3IgYW1wbGljb24gc2VxdWVuY2luZyBidXQgdGhlIHJhdyBtYWNoaW5lIG91dHB1dCBpcyBkaWZmZXJlbnQgdGhhbiBJbGx1bWluYS4gSW9uIGRvZXMgbm90IHVzZSB0aGUgcGFpcmVkIGVuZCByZWFkIHN5c3RlbTsgdGh1cywgd2Uga2VlcCBmb3J3YXJkIGFuZCByZXZlcnNlIHNlcXVlbmNlcyBzZXBhcmF0ZSBhbmQgKmRvIG5vdCogIHRyeSB0byBqb2luIHNlcXVlbmNlcy4gDQoNCiMjIyAqKjEpKiogT3JnYW5pemUgRm9yd2FyZCBhbmQgUmV2ZXJzZSBGaWxlcw0KIyMjIyBBbXBsaWNvbnMgYXJlIHJlYWQgaW4gZWl0aGVyIGZvcndhcmQgKipfb3JfKiogIHJldmVyc2UgZGlyZWN0aW9uLCBkZXBlbmRpbmcgb24gd2hpY2ggZW5kIGF0dGFjaGVkIHRvIHRoZSBJb24gY2hpcC4gVGh1cywgd2UgZXhwZWN0IDEgRkFTVFEgZmlsZSBmb3IgZWFjaCB1bmlxdWUgYmFyY29kZSB1c2VkLiBJbiBvdXIgY2FzZSwgd2UgZG91YmxlIGJhcmNvZGVkIHNhbXBsZXMgKG4gPSA1MDsgNDYgYmF0IHNhbXBsZXMgKyA0IGJsYW5rcykgd2l0aCAxMCB1bmlxdWUgZm9yd2FyZCBwcmltZXJzIGFuZCA1IHVuaXF1ZSByZXZlcnNlIHByaW1lcnMsIHNvIHdlIGV4cGVjdCAxNSBmYXN0cSBmaWxlcy4gV2Uga25vdyB0aGUgZmlsZXMgMS0tMTAgd2VyZSBzZXF1ZW5jZWQgaW4gdGhlIGZvcndhcmQgZGlyZWN0aW9uIGFuZCBmaWxlcyAxMS0tMTUgd2VyZSByZWFkIGluIHRoZSByZXZlcnNlIGRpcmVjdGlvbi4gVGhlIHJhdyBvdXRwdXQgZm9sZGVyIHNob3VsZCBsb29rIGxpa2UgdGhpczoNCg0KDQp8ICoqRmlsZSBOYW1lKiogICB8ICoqRGlyZWN0aW9uKiogfA0KfDotLS0tLS0tLS0tLS0tLS06fDotLS0tLS0tLS0tLS0tOnwNCnwgMjAxNS0wMy0yMC5Jb25YcHJlc3NfMDAxLmZhc3RxIHwgZm9yd2FyZCAgfA0KfCAyMDE1LTAzLTIwLklvblhwcmVzc18wMDIuZmFzdHEgfCBmb3J3YXJkICB8DQp8IDIwMTUtMDMtMjAuSW9uWHByZXNzXzAwMy5mYXN0cSB8IGZvcndhcmQgIHwNCnwgLiAuIC4gLiAuIC4gLiAuIC4gICAgICAgICAgICAgIHwgLiAuIC4gICAgfA0KfCAyMDE1LTAzLTIwLklvblhwcmVzc18wMTQuZmFzdHEgfCByZXZlcnNlICB8DQp8IDIwMTUtMDMtMjAuSW9uWHByZXNzXzAxNS5mYXN0cSB8IHJldmVyc2UgIHwNCjxicj4NCg0KIyMjIyBDcmVhdGUgYSBuZXcgZm9sZGVyIGFuZCBtb3ZlIHRoZSBleHBlY3RlZCBmaWxlcyB0byB0aGF0IGRpcmVjdG9yeSAoaS5lLiwgSW9uWHByZXNzXzAwMSB0byBJb25YcHJlc3NfMDE1KS4gVGhlcmUgd2lsbCBiZSBvdGhlciBmaWxlcyBpbiB0aGUgZGlyZWN0b3J5IGNvbnRhaW5pbmcgcmVhZHMgbm90IG1hcHBlZCBiYWNrIHRvIGEgc2FtcGxlIGJ5IGZvcndhcmQvcmV2ZXJzZSBiYXJjb2RlIGNvbWJpbmF0aW9uIChpLmUuLCBJb25YcHJlc3NfMDc1KS4gT3VyIG5ldyBkaXJlY3RvcnkgaXMgY2FsbGVkICoqYDIwMTRJT05gKioNCg0KIyMjIyBJb24gVG9ycmVudCByZXN1bHRzIGFyZSBub3QgZGVtdWx0aXBsZXhlZCBzbyBmaXJzdCB3ZSBjcmVhdGVkIDIgc3ViLWZvbGRlcnMsICoqYGZvcndhcmRgKiogYW5kICoqYHJldmVyc2VgKiosIGFuZCBwdXQgdGhlIGFwcHJvcHJpYXRlIElvblhwcmVzcyBmYXN0cSBmaWxlcyBpbnRvIGVhY2ggb25lLiBOZXh0LCB3ZSBwZXJmb3JtIHNldmVyYWwgc3RlcHMgdG8gcHJlcGFyZSBhbGwgdGhlIGZvcndhcmQgRkFTVFEgZmlsZXMsIHRoZW4gcmVwZWF0IHRoZSBwcm9jZXNzIHdpdGggdGhlIHJldmVyc2UgRkFTVFEgZmlsZXMsIHRoZW4gcHV0IGFsbCBmaWxlcyBpbnRvIDEgRkFTVEEgYmVmb3JlIHBpY2tpbmcgT1RVcy4NCg0KYGBge3IsIGVuZ2luZT0iYmFzaCIsIGVjaG89VFJVRX0NCmNkIDIwMTRJT04NCg0KbWtkaXIgZm9yd2FyZA0KDQpta2RpciByZXZlcnNlDQoNCm12ICowMDEqICowMDIqICowMDMqICowMDQqICowMDUqICowMDYqICowMDcqICowMDgqICowMDkqICowMTAqICAuL2ZvcndhcmQNCg0KbXYgKjAxMSogKjAxMiogKjAxMyogKjAxNCogKjAxNSogIC4vcmV2ZXJzZQ0KYGBgDQo8YnI+DQoNCiMjIyAqKjIpKiogUHJlcGFyZSBCYXJjb2RlcyBmb3IgZWFjaCBGaWxlDQojIyMjVG8gc2ltcGxpZnkgdGhlIGRlbXVsdGlwbGV4aW5nIHByb2Nlc3MsIHdlIG1vdmVkIHRoZSAxMCBicCByZXZlcnNlIGJhcmNvZGVzIHRvIHRoZSBmcm9udCwganVzdCBhZnRlciB0aGUgZm9yd2FyZCBiYXJjb2RlLCB0byBjcmVhdGUgYSBuZXcgMjAgYnAgdW5pcXVlICdiYXJjb2RlJyBmb3IgZWFjaCBzZXF1ZW5jZS4gRm9yIGV4YW1wbGU6DQpgYGB7ciwgZW5naW5lPSJiYXNoIiwgZWNobz1UUlVFfQ0KY2QgZm9yd2FyZCANCg0KI05vdGUgdGhhdCB0aGUgMTBicCBmb3J3YXJkIGJhcmNvZGUgY2hhbmdlcyBpbiBlYWNoIGNvbW1hbmQgY29ycmVzcG9uZCB0byBlYWNoIGZpbGUNCiNUaGUgY29tbWFuZCBzZWFyY2hlcyB0aGUgZmFzdHEgZmlsZSBhbmQgbW92ZXMgdGhlIGxhc3QgMTBicCB0byBqdXN0IGFmdGVyIHRoZSBmb3J3YXJkIGJhcmNvZGUgZm9yIGVhY2ggcmVhZA0KDQpzZWQgJzJ+NHMvXCguKlwpXCguXHsxMFx9XCkkL0dUVEFDQ1RUQUdcMlwxLzsnIDwgMjAxNS0wMy0yMC5Jb25YcHJlc3NfMDAxLmZhc3RxID4gRjAxX2JhcmNvZGVzLmZhc3RxDQoNCnNlZCAnMn40cy9cKC4qXClcKC5cezEwXH1cKSQvR1RUQ1RDQ1RUQVwyXDEvOycgPCAyMDE1LTAzLTIwLklvblhwcmVzc18wMDIuZmFzdHEgPiBGMDJfYmFyY29kZXMuZmFzdHENCg0Kc2VkICcyfjRzL1woLipcKVwoLlx7MTBcfVwpJC9HQUFUQ0NUQ1RUXDJcMS87JyA8IDIwMTUtMDMtMjAuSW9uWHByZXNzXzAwMy5mYXN0cSA+IEYwM19iYXJjb2Rlcy5mYXN0cQ0KDQpzZWQgJzJ+NHMvXCguKlwpXCguXHsxMFx9XCkkL0dBVENUVEdHVEFcMlwxLzsnIDwgMjAxNS0wMy0yMC5Jb25YcHJlc3NfMDA0LmZhc3RxID4gRjA0X2JhcmNvZGVzLmZhc3RxDQoNCnNlZCAnMn40cy9cKC4qXClcKC5cezEwXH1cKSQvR1RUQ0NUVENUR1wyXDEvOycgPCAyMDE1LTAzLTIwLklvblhwcmVzc18wMDUuZmFzdHEgPiBGMDVfYmFyY29kZXMuZmFzdHENCg0Kc2VkICcyfjRzL1woLipcKVwoLlx7MTBcfVwpJC9HQUFDVFRHQ0FHXDJcMS87JyA8IDIwMTUtMDMtMjAuSW9uWHByZXNzXzAwNi5mYXN0cSA+IEYwNl9iYXJjb2Rlcy5mYXN0cQ0KDQpzZWQgJzJ+NHMvXCguKlwpXCguXHsxMFx9XCkkL0dBQVRDQUNHQUFcMlwxLzsnIDwgMjAxNS0wMy0yMC5Jb25YcHJlc3NfMDA3LmZhc3RxID4gRjA3X2JhcmNvZGVzLmZhc3RxDQoNCnNlZCAnMn40cy9cKC4qXClcKC5cezEwXH1cKSQvR1RUQVRDR0dBQVwyXDEvOycgPCAyMDE1LTAzLTIwLklvblhwcmVzc18wMDguZmFzdHEgPiBGMDhfYmFyY29kZXMuZmFzdHENCg0Kc2VkICcyfjRzL1woLipcKVwoLlx7MTBcfVwpJC9HVFRDQ0dDVENBXDJcMS87JyA8IDIwMTUtMDMtMjAuSW9uWHByZXNzXzAwOS5mYXN0cSA+IEYwOV9iYXJjb2Rlcy5mYXN0cQ0KDQpzZWQgJzJ+NHMvXCguKlwpXCguXHsxMFx9XCkkL0dUVENHR1RDQUdcMlwxLzsnIDwgMjAxNS0wMy0yMC5Jb25YcHJlc3NfMDEwLmZhc3RxID4gRjEwX2JhcmNvZGVzLmZhc3RxDQpgYGANCjxicj4NCg0KIyMjICoqMykqKiBDb25jYXRlbmF0ZSBGb3J3YXJkIEZBU1RRIGZpbGVzDQojIyMjIEFsbCBzZXF1ZW5jZXMgc3RpbGwgaGF2ZSBmb3J3YXJkIGFuZCByZXZlcnNlIGJhcmNvZGVzIGF0dGFjaGVkLCBpbiBhIG5ldyB1bmlxdWUgMjAgYnAgZm9yd2FyZCBiYXJjb2RlLCBzbyB0aGVyZSBpcyBubyBjaGFuY2Ugb2YgbWl4aW5nIHVwIHNlcXVlbmNlcyBieSBob3N0IHNhbXBsZS4NCmBgYHtyLCBlbmdpbmU9ImJhc2giLCBlY2hvPVRSVUV9DQpjYXQgKl9iYXJjb2Rlcy5mYXN0cSA+IGZvcndhcmRzZXFzLmZhc3RxDQpgYGANCjxicj4NCg0KIyMjICoqNCkqKiBDb252ZXJ0IEZBU1RRIHRvIEZBU1RBDQojIyMjIFdlIG5lZWQgc2VwYXJhdGUgRkFTVEEgYW5kIFFVQUwgZmlsZXMgZm9yIGRlbXVsdGlwbGV4aW5nIGFuZCBxdWFsaXR5IGZpbHRlcmluZyBiZWNhdXNlIGRvd25zdHJlYW0gUUlJTUUgc2NyaXB0cyByZXF1aXJlIEZBU1RBIGZvcm1hdCBhcyBpbnB1dC4NCmBgYHtyLCBlbmdpbmU9ImJhc2giLCBlY2hvPVRSVUV9DQpjb252ZXJ0X2Zhc3RhcXVhbF9mYXN0cS5weSAtZiBmb3J3YXJkc2Vxcy5mYXN0cSAtYyBmYXN0cV90b19mYXN0YXF1YWwgICN0b29rIH4yNSBzZWNvbmRzIHdpdGggdGVzdCBzZXQgDQpgYGANCiMjIyMgVGhpcyB3aWxsIGNyZWF0ZWQgMiBuZXcgZmlsZXMgaW4gdGhlICoqYGZvcndhcmRgKiogZGlyZWN0b3J5OiAqKmBmb3J3YXJkc2Vxcy5mbmFgKiogYW5kICoqYGZvcndhcmRzZXFzLnF1YWxgKiouIFRoZXNlIGFyZSB0aGUgbmV3IEZBU1RBIGZpbGUgKC5mbmEpIGFuZCB0aGUgYXNzb2NpYXRlZCBxdWFsaXR5IGZpbGUgKFFVQUwpLg0KPGJyPg0KDQojIyMgKio1KSoqIFZhbGlkYXRlIE1hcHBpbmcgRmlsZQ0KIyMjIyBXZSB2YWxpZGF0ZSB0aGUgbWFwcGluZyBmaWxlIHRoYXQgdGVsbHMgUUlJTUUgd2hpY2ggd2hpY2ggYmFyY29kZXMgYW5kIHByaW1lcnMgYmVsb25nIHRvIGVhY2ggc2FtcGxlIHNvIHRoYXQgd2UgY2FuIG1haW50YWluIHRoZSBwYXRoIGZyb20gc2VxdWVuY2VzIGJhY2sgdG8gaG9zdCBzYW1wbGVzLiBNYWtlIHN1cmUgdGhlICoqYFNhbXBsZU1hcEYudHh0YCoqIGZpbGUgaXMgaW4gdGhlICoqYGZvcndhcmRgKiogZGlyZWN0b3J5Lg0KYGBge3IsIGVuZ2luZT0iYmFzaCIsIGVjaG89VFJVRX0NCmNkIC4uICAgICAgICAgICAgICAgICAgICNjaGFuZ2UgYmFjayB0byAyMDE0SU9OIGRpcg0KDQp2YWxpZGF0ZV9tYXBwaW5nX2ZpbGUucHkgLW0gU2FtcGxlTWFwRi50eHQNCg0KaGVhZCBTYW1wbGVNYXBGLnR4dA0KYGBgDQojIyMjIElmIFFJSU1FIGZsYWdzIGFueSBlcnJvcnMsIG1ha2UgY2hhbmdlcyBhcyBuZWNlc3Nhcnk7IGhlbHAgY2FuIGJlIGZvdW5kIGhlcmU6IGh0dHA6Ly9xaWltZS5vcmcvc2NyaXB0cy92YWxpZGF0ZV9tYXBwaW5nX2ZpbGUuaHRtbA0KPGJyPg0KDQojIyMjVGhlIG1hcHBpbmcgZmlsZSBzaG91bGQgbG9vayBsaWtlIHRoaXMuIE5vdGljZSB0aGUgbmV3IDIwIGJwIGJhcmNvZGUgY3JlYXRlZCBpbiBzdGVwICoqMikqKiBhbmQgdGhlIElvbi1zcGVjaWZpYyAqKkdBVCoqIGFkYXB0ZXIgb24gdGhlIHJldmVyc2UgcHJpbWVyOg0KIVtdKEM6XFxVc2Vyc1xcT3duZXJcXEdvb2dsZSBEcml2ZVxcSU9OdnNNSVNFUVxcQmF0RGlldFdvcmtmbG93X2ZpbGVzXFxTYW1wbGVNYXBGLmpwZykNCg0KDQojIyMgKio2KSoqIERlbXVsdGlwbGV4IGFuZCBRdWFsaXR5IEZpbHRlciAgDQojIyMjIER1cmluZyB0aGlzIHN0ZXAsIHdlIHF1YWxpdHkgZmlsdGVyIGJhc2UgY2FsbHMgbGVzcyB0aGFuIFEyMCBhbmQgc2VxdWVuY2VzIGxlc3MgdGhhbiAyMDAgYnAsIGFzc2lnbiBRSUlNRSBsYWJlbHMgdG8gZWFjaCBzZXF1ZW5jZSwgY29ycmVzcG9uZGluZyB0byBob3N0IHNhbXBsZSwgYW5kIHRoZW4gcmVtb3ZlIHRoZSBuZXcgMjAgYnAgYmFyY29kZSBhbmQgYm90aCBwcmltZXJzLiBUaGVzZSBwYXJhbWV0ZXJzIGNhbiBiZSBjaGFuZ2VkIHdpdGggdGhlICoqYC1zIChtaW5fcXVhbF9zY29yZSlgKiogYW5kICoqYC1sIChtaW5fc2VxX2xlbmd0aClgKiogb3B0aW9ucy4gV2UgYWxzbyByZW1vdmUgYW55IHNlcXVlbmNlcyB3aXRoIGEgaG9tb3BvbHltZXIgcnVuIG9mIDEwIG9yIG1vcmUgYnA7IHRoZXJlIGlzIGEgbmF0dXJhbCA4IGJwIGNvbnNlcnZlZCByZWdpb24gaW4gb3VyIHRhcmdldCBhcmVhLiBUaGUgZXhwZWN0ZWQgbGVuZ3RoIGF0IHRoaXMgcG9pbnQgaXMgMjM0IGJwLg0KDQpgYGB7ciwgZW5naW5lPSJiYXNoIiwgZWNobz1UUlVFfQ0Kc3BsaXRfbGlicmFyaWVzLnB5IC1tIFNhbXBsZU1hcEYudHh0IC1mIC4vZm9yd2FyZC9mb3J3YXJkc2Vxcy5mbmEgLXEgLi9mb3J3YXJkL2ZvcndhcmRzZXFzLnF1YWwgLW8gZGVtdWx0aXBsZXhlZEYgLWIgMjAgLUggMTAgLU0gMSAtcyAyMCAteiB0cnVuY2F0ZV9yZW1vdmUgICAjdG9vayAxIG1pbiwgNyBzZWMgd2l0aCB0ZXN0IHNldA0KYGBgDQojIyMjIyoqVGhpcyBzdGVwIGNhbiB0YWtlIGEgd2hpbGUgdG8gcnVuLCBzbyBvbmUgY2FuIG1ha2Ugc3VyZSBRSUlNRSBpcyBub3QgaHVuZyB1cCBieSBvY2Nhc2lvbmFsbHkgZ29pbmcgaW50byB0aGUgbmV3bHkgY3JlYXRlZCBkaXJlY3RvcnkgYW5kIHJpZ2h0IGNsaWNraW5nIG9uIHRoZSBvdXRwdXQgZmlsZSB0byBjaGVjayBmaWxlIHNpemUgYW5kIG1ha2Ugc3VyZSBpdCBncm93cyBiZXR3ZWVuIGNoZWNrcy4gVGhlIHByb2Nlc3MgaXMgZG9uZSB3aGVuIHRoZSBjdXJzb3IgcHJvbXB0IHJldHVybnMgdG8gdGhlIHRlcm1pbmFsIHdpbmRvdy4qKg0KPGJyPg0KDQojIyMgKio3KSoqIFJlcGVhdCBzdGVwcyAyLS02IGZvciBSZXZlcnNlIEZBU1RRIGZpbGVzDQojIyMjIyoqTm90ZSB0aGF0IGEgc2VwYXJhdGUgbWFwcGluZyBmaWxlIGlzIG5lZWRlZCB3aXRoIHByaW1lciBzZXF1ZW5jZXMgYWxzbyByZXZlcnNlIGNvbXBsZW1lbnRlZDogYFNhbXBsZU1hcFIudHh0YC4qKg0KYGBge3IsIGVuZ2luZT0iYmFzaCIsIGVjaG89VFJVRX0NCmNkIC4vcmV2ZXJzZQ0KDQpzZWQgJzJ+NHMvXCguKlwpXCguXHsxMFx9XCkkL0dBVFRDR0FHR0FcMlwxLzsnIDwgMjAxNS0wMy0yMC5Jb25YcHJlc3NfMDExLmZhc3RxID4gUjExX2JhcmNvZGVzLmZhc3RxDQoNCnNlZCAnMn40cy9cKC4qXClcKC5cezEwXH1cKSQvR0FBQ0NBQ0NUQVwyXDEvOycgPCAyMDE1LTAzLTIwLklvblhwcmVzc18wMTIuZmFzdHEgPiBSMTJfYmFyY29kZXMuZmFzdHENCg0Kc2VkICcyfjRzL1woLipcKVwoLlx7MTBcfVwpJC9HVENDR1RUQUdBXDJcMS87JyA8IDIwMTUtMDMtMjAuSW9uWHByZXNzXzAxMy5mYXN0cSA+IFIxM19iYXJjb2Rlcy5mYXN0cQ0KDQpzZWQgJzJ+NHMvXCguKlwpXCguXHsxMFx9XCkkL0dBQ0FDVENDQUFcMlwxLzsnIDwgMjAxNS0wMy0yMC5Jb25YcHJlc3NfMDE0LmZhc3RxID4gUjE0X2JhcmNvZGVzLmZhc3RxDQoNCnNlZCAnMn40cy9cKC4qXClcKC5cezEwXH1cKSQvR0FDQ1RDVEFHQVwyXDEvOycgPCAyMDE1LTAzLTIwLklvblhwcmVzc18wMTUuZmFzdHEgPiBSMTVfYmFyY29kZXMuZmFzdHENCg0KY2F0ICpfYmFyY29kZXMuZmFzdHEgPiByZXZlcnNlc2Vxcy5mYXN0cQ0KDQpjb252ZXJ0X2Zhc3RhcXVhbF9mYXN0cS5weSAtZiByZXZlcnNlc2Vxcy5mYXN0cSAtYyBmYXN0cV90b19mYXN0YXF1YWwNCiNjcmVhdGVzIDIgbmV3IGZpbGVzOiByZXZlcnNlc2Vxcy5mbmEgYW5kIHJldmVyc2VzZXFzLnF1YWwNCmNkIC4uDQoNCnZhbGlkYXRlX21hcHBpbmdfZmlsZS5weSAtbSBTYW1wbGVNYXBSLnR4dA0KDQpzcGxpdF9saWJyYXJpZXMucHkgLW0gU2FtcGxlTWFwUi50eHQgLWYgLi9yZXZlcnNlL3JldmVyc2VzZXFzLmZuYSAtcSAuL3JldmVyc2UvcmV2ZXJzZXNlcXMucXVhbCAtbyBkZW11bHRpcGxleGVkUiAtYiAyMCAtSCAxMCAtTSAxIC1zIDIwIC16IHRydW5jYXRlX3JlbW92ZSAgICAgICAgICAgICAgICAgI2lmIHlvdSBnZXQgYSBoaWdoIG51bWJlciBvZiBtaXNtYXRjaGVzIGFuZCBzZXF1ZW5jZXMgYXJlIGRpc2NhcmRlZCwgZG91YmxlIGNoZWNrIHRoYXQgeW91IGhhdmUgdGhlIHJpZ2h0IG1hcHBpbmcgZmlsZQ0KYGBgDQojIyMjIyoqVGhpcyBzdGVwIGNhbiB0YWtlIGEgd2hpbGUgdG8gcnVuLCBzbyBvbmUgY2FuIG1ha2Ugc3VyZSBRSUlNRSBpcyBub3QgaHVuZyB1cCBieSBvY2Nhc2lvbmFsbHkgZ29pbmcgaW50byB0aGUgbmV3bHkgY3JlYXRlZCBkaXJlY3RvcnkgYW5kIHJpZ2h0IGNsaWNraW5nIG9uIHRoZSBvdXRwdXQgZmlsZSB0byBjaGVjayBmaWxlIHNpemUgYW5kIG1ha2Ugc3VyZSBpdCBncm93cyBiZXR3ZWVuIGNoZWNrcy4gVGhlIHByb2Nlc3MgaXMgZG9uZSB3aGVuIHRoZSBjdXJzb3IgcHJvbXB0IHJldHVybnMgdG8gdGhlIHRlcm1pbmFsIHdpbmRvdy4qKg0KPGJyPg0KDQojIyMgKio4KSoqIENvbmNhdGVuYXRlIEZvcndhcmQgYW5kIFJldmVyc2UgdG8gMSBGaWxlDQojIyMjIEZpcnN0IHdlIHJlbmFtZSB0aGUgZm9yd2FyZCBGQVNUQSBmaWxlIChjb250YWluaW5nIGFsbCB0aGUgZm9yd2FyZCBzZXF1ZW5jZXMgbm93KSBhbmQgbW92ZSBpdCB0byBvdXIgbWFpbiBwcm9qZWN0IGZvbGRlci4gUmVwZWF0IGZvciB0aGUgcmV2ZXJzZSBGQVNUQSBmaWxlLCByZXZlcnNlIGNvbXBsZW1lbnQsIGFuZCB0aGVuIGNvbmNhdGVuYXRlIGFsbCBzZXF1ZW5jZXMgaW50byBhIHNpbmdsZSBmaWxlIHdpdGggZXZlcnl0aGluZyBpbiB0aGUgNScgLS0+IDMnIG9yaWVudGF0aW9uLg0KDQojIyMjV2UgcmV2ZXJzZSBjb21wbGVtZW50IHRoZSBzZXF1ZW5jZXMgdXNpbmcgdGhlIEZBU1RYIFRvb2xraXQsIHdoaWNoIG11c3QgYmUgaW5zdGFsbGVkIGluIG91ciBRSUlNRSBWaXJ0dWFsIEJveCBvciBkaXJlY3RseSBpbiBNYWNxaWltZSBvciBMaW51eCBpbiB0aGUgbWFpbiB3b3JraW5nIGRpcmVjdG9yeS4gV2UgdXNlZCBhIGxvY2FsIGNvcHkgb2YgRkFTVFggVG9vbGtpdCAwLjAuMTIuIFJldmVyc2UgY29tcGxlbWVudGluZyBjYW4gYWxzbyBiZSBkb25lIHdpdGggdGhlIFFJSU1FICoqYGFkanVzdF9zZXFfb3JpZW50YXRpb24ucHlgKiogc2NyaXB0LiBXZSB1c2VkIHRoZSBGQVNUWCBjb21tYW5kIGJlY2F1c2Ugd2Ugd2lsbCB1c2UgYW5vdGhlciBGQVNUWCB0b29sIGxhdGVyIGluIHRoaXMgc2VjdGlvbi4NCmBgYHtyLCBlbmdpbmU9ImJhc2giLCBlY2hvPVRSVUV9DQpjZCBkZW11bHRpcGxleGVkRg0KDQptdiBzZXFzLmZuYSBGc2Vxcy5mbmENCg0KbXYgRnNlcXMuZm5hIC4uDQoNCmNkIC4uDQoNCmNkIC4vZGVtdWx0aXBsZXhlZFINCg0KbXYgc2Vxcy5mbmEgUnNlcXMuZm5hDQoNCm12IFJzZXFzLmZuYSAuLg0KDQpjZCAuLg0KDQpmYXN0eF9yZXZlcnNlX2NvbXBsZW1lbnQgLWkgLi9Sc2Vxcy5mbmEgIC1vIC4vUnNlcXNfZmxpcHBlZC5mbmENCg0KY2F0IEZzZXFzLmZuYSBSc2Vxc19mbGlwcGVkLmZuYSA+IDIwMTRpb25zZXFzLmZuYQ0KYGBgDQo8YnI+DQoNCiMjIyAqKjkpKiogQ2x1c3RlciBTaW1pbGFyIFNlcXVlbmNlcw0KIyMjI05leHQgd2UgY2x1c3RlciBzaW1pbGFyIHNlcXVlbmNlcyB1c2luZyB0aGUgbG9jYWwgYWxpZ25tZW50ICdzd2FybScgbWV0aG9kIGFuZCBhbGxvd2luZyBvbmx5IGEgMiBicCBtaXNtYXRjaC4NCg0KIyMjIyMjTWFo6SBGLCBSb2duZXMgVCwgUXVpbmNlIEMsIGRlIFZhcmdhcyBDLCBEdW50aG9ybiBNLiAoMjAxNCkgU3dhcm06IHJvYnVzdCBhbmQgZmFzdCBjbHVzdGVyaW5nIG1ldGhvZCBmb3IgYW1wbGljb24tYmFzZWQgc3R1ZGllcy4gUGVlckogMjplNTkzIDxodHRwOi8vZHguZG9pLm9yZy8xMC43NzE3L3BlZXJqLjU5Mz4NCg0KYGBge3IsIGVuZ2luZT0iYmFzaCIsIGVjaG89VFJVRX0gDQpwaWNrX290dXMucHkgLWkgLi8yMDE0aW9uc2Vxcy5mbmEgLW0gc3dhcm0gLS1zd2FybV9yZXNvbHV0aW9uIDIgLW8gLi9zd2FybU9UVXMgICAjdG9vayAxLjggc2VjIHdpdGggdGVzdCBzZXQNCmBgYA0KIyMjIyBOb3cgd2UgaGF2ZSBhIG5ldyBkaXJlY3Rvcnkgd2l0aCB0aGUgY2x1c3RlcnMgb2Ygc2VxdWVuY2VzOiAqKmBzd2FybU9UVXNgKioNCg0KIyMjIyMqKlRoaXMgc3RlcCBjYW4gdGFrZSBhIHdoaWxlIHRvIHJ1biwgYW5kIG5vIGZpbGVzIGFyZSBwcm9kdWNlZCB1bnRpbCB0aGUgcHJvY2VzcyBpcyBjb21wbGV0ZS4gU28gb25lIGNhbiBtYWtlIHN1cmUgUUlJTUUgaXMgbm90IGh1bmcgdXAgYnkgdXNpbmcgdGhlKiogKipgdG9wYCoqICoqVU5JWCBjb21tYW5kIGluIGEgbmV3IHRlcm1pbmFsIHdpbmRvdy4gVGhlIHBpY2stb3R1cyBRSUlNRSBjb21tYW5kIHNob3VsZCBiZSBhdCB0aGUgdG9wIG9mIHRoZSBsaXN0IGFuZCB1c2luZyB0aGUgZ3JlYXRlc3QgJUNQVS4qKg0KPGJyPg0KDQojIyMgKioxMCkqKiBCdWlsZCBhbmQgRmlsdGVyIE9UVSBPY2N1cnJlbmNlIFRhYmxlIChCSU9NKQ0KIyMjI1dlIG5vdyBjcmVhdGUgb3VyIEJJT00gdGFibGUgdG8ga2VlcCB0cmFjayBvZiB3aGljaCBPVFVzIHdlcmUgcHJlc2VudCBpbiBlYWNoIHNhbXBsZS4gV2UgdXNlIHRoZSBzd2FybSBvdXRwdXQgZmlsZSBgMjAxNGlvbnNlcXNfb3R1cy50eHRgIGFzIGlucHV0Lg0KYGBge3IsIGVuZ2luZT0iYmFzaCIsIGVjaG89VFJVRX0NCm1ha2Vfb3R1X3RhYmxlLnB5IC1pIC4vc3dhcm1PVFVzLzIwMTRpb25zZXFzX290dXMudHh0IC1vIC4vc3dhcm1PVFVzL3NlcXMuYmlvbQ0KYGBgDQojIyMjV2UgZmlsdGVyZWQgb3V0IGxvdyBhYnVuZGFuY2UgT1RVIGNsdXN0ZXJzICg8IDEwIGNvcGllcyBpbiBhdCBsZWFzdCAxIHNhbXBsZSBvZiB0aGUgZW50aXJlIGRhdGEgc2V0KSBiZWZvcmUgd3JpdGluZyBkYXRhIHRvIHRoZSB0YWJsZSB1c2luZyBhIHNjcmlwdCB0aGF0IGNhbGxzIHRoZSAncGFuZGFzJyBweXRob24gcGFja2FnZS4gV2UgdXNlZCBQeXRob24gMi43LjMgdGhhdCBzaG91bGQgY29tZSBhcyBhIGRlcGVuZGVuY3kgd2l0aCB0aGUgUUlJTUUgaW5zdGFsbC4gVGhlIHByb3ZpZGVkICdwYW5kYXNfZmlsdGVyMTAucHknIHNjcmlwdCBoYXMgdG8gYmUgaW4gdGhlICoqYHN3YXJtT1RVc2AqKiBkaXJlY3RvcnkuICANCg0KYGBge3IsIGVuZ2luZT0iYmFzaCIsIGVjaG89VFJVRX0NCmNkIC4vc3dhcm1PVFVzICAgICAjY2hhbmdlIHRvIHRoZSBuZXcgZGlyZWN0b3J5DQoNCmNwIC4uL3BhbmRhc19maWx0ZXIxMC5weSAuDQoNCnB5dGhvbiBwYW5kYXNfZmlsdGVyMTAucHkgICNUaGlzIHNjcmlwdCB3aWxsIGZpbmQgdGhlIHNlcXMuYmlvbSBmaWxlIGNyZWF0ZWQgYXMgb3V0cHV0IGluIHRoZSBsYXN0IHN0ZXANCmBgYA0KIyMjI1RoaXMgc2NpcHQgY3JlYXRlcyBhIG5ldyBmaWxlIGNhbGxlZCAqKmBleGNsdWRlLnR4dGAqKiB0aGF0IHdlIGNhbiB1c2UgaW4gdGhlIG5leHQgc3RlcCB0byByZW1vdmUgdGhvc2UgbG93IGFidW5kYW5jZSBPVFUgY2x1c3RlcnMuICANCg0KIyMjI0FmdGVyIHJlbW92aW5nIHRoZSB1bndhbnRlZCBsb3cgYWJ1bmRhbmNlIE9UVSBjbHVzdGVycywgd2Ugd3JpdGUgdGhlIGRlc2lyZWQgT1RVcyB0byBhIEJJT00gdGFibGUgaW4gaHVtYW4tcmVhZGFibGUgdGFidWxhciBmb3JtYXQuIFRvIGxhYmVsIHRoZSBkZW5vdm8gT1RVcywgd2UgdXNlIHRoZSAqKmBwaWNrX3JlcF9zZXQucHlgKiogc2NyaXB0IHRvIHBpY2sgb25lIHJlcHJlc2VudGF0aXZlIHNlcXVlbmNlIGZyb20gZWFjaCBjbHVzdGVyLiBUaGVuIHdlIHB1bGwgdGhvc2UgZGVzaXJlZCByZXByZXNlbnRhdGl2ZSBzZXF1ZW5jZXMgZnJvbSBvdXIgb3JpZ2luYWwgLmZuYSBmaWxlIGFuZCB3cml0ZSBhIG5ldyAuZm5hLiBGcm9tIGhlcmUgb24gb3V0LCB3ZSB1c2UgdGhlIHJlcHJlc2VudGF0aXZlIHNlcXVlbmNlcyBmcm9tIGVhY2ggT1RVIGNsdXN0ZXIgdG8gcmVkdWNlIHByb2Nlc3NpbmcgZGVtYW5kLg0KDQpgYGB7ciwgZW5naW5lPSJiYXNoIiwgZWNobz1UUlVFfQ0KDQpjZCAuLiAgICAgI2NoYW5nZSBiYWNrIHRvIHRoZSBtYWluIHdvcmtpbmcgZGlyZWN0b3J5DQoNCmZpbHRlcl9vdHVzX2Zyb21fb3R1X3RhYmxlLnB5IC1pIC4vc3dhcm1PVFVzL3NlcXMuYmlvbSAtbyAuL3N3YXJtT1RVcy9vdHVfdGFibGVfbm9fc2luZ2xldG9ucy5iaW9tIC1lIC4vc3dhcm1PVFVzL2V4Y2x1ZGUudHh0DQoNCmJpb20gY29udmVydCAtaSAuL3N3YXJtT1RVcy9vdHVfdGFibGVfbm9fc2luZ2xldG9ucy5iaW9tIC1vIC4vc3dhcm1PVFVzLzIwMTRpb25fYmlvbV9ub19zaW5nbGV0b25zLnR4dCAtLXRhYmxlLXR5cGU9Ik9UVSB0YWJsZSIgLS10by10c3YNCg0KcGlja19yZXBfc2V0LnB5IC1pIC4vc3dhcm1PVFVzLzIwMTRpb25zZXFzX290dXMudHh0IC1mIC4vMjAxNGlvbnNlcXMuZm5hIC1tIG1vc3RfYWJ1bmRhbnQgLW8gLi8yMDE0aW9uX2ZpbmFsLmZuYSAtbCAuLzIwMTRpb25fZmluYWxfbG9nDQoNCmZpbHRlcl9mYXN0YS5weSAtZiAuLzIwMTRpb25fZmluYWwuZm5hIC1iIC4vc3dhcm1PVFVzL290dV90YWJsZV9ub19zaW5nbGV0b25zLmJpb20gLW8gLi8yMDE0aW9uX2ZpbmFsX25vX3NpbmdsZXRvbnMuZm5hDQpgYGANCiMjIyNUaGUgbGFzdCBjb21tYW5kIGluIFVOSVggd2lsbCBjb252ZXJ0IG91ciBmaW5hbCBGQVNUQSBmaWxlIHRvIGEgdGFiLWRlbGltaXRlZCBmaWxlIHdlIGNhbiB1c2UgdG8gYXNzaWduIHRheG9ub215IGluIHRoZSBCT0xEIGRhdGFiYXNlLiBUaGlzIGZpbGUgd2lsbCBiZSB1c2VmdWwgd2hlbiByZXNvbHZpbmcgdGF4b25vbWljIGRpc2NyZXBhbmNpZXMgaW4gdGhlIGxhc3Qgc2VjdGlvbjogW01hbnVhbCBWZXR0aW5nXSgjTWFudWFsIFZldHRpbmcpLiBUaGUgKipgZmFzdGFfZm9ybWF0dGVyYCoqIGNvbW1hbmQgaXMgcGFydCBvZiB0aGUgRkFTVFggVG9vbGtpdC4gV2UgcnVuIHRoZSBjb21tYW5kIGFuZCB0aGVuIG1hbnVhbGx5IGFkZCBjb2x1bW4gaGVhZGVycyB0byB0aGUgdGV4dCBmaWxlIGNhbGxlZDogKipzZXFJRCoqIGFuZCAqKnNlcXMqKi4gIA0KDQpgYGB7ciwgZW5naW5lPSJiYXNoIiwgZWNobz1UUlVFfQ0KZmFzdGFfZm9ybWF0dGVyIC1pIC4vMjAxNGlvbl9maW5hbF9ub19zaW5nbGV0b25zLmZuYSAtbyAuLzIwMTRpb250YWJzZXFzLnR4dCAtdA0KYGBgDQoNCjxicj4NCg0KIzxhIGlkPSJBc3NpZ24gVGF4b25vbXkiPjwvYT5Bc3NpZ24gVGF4b25vbXkgYW5kIEZpbHRlciBSZXN1bHRzIC0tIF9fX1J1biBjb21tYW5kcyBpbiBSX19fDQoNCiMjIyNBZnRlciB0cmFuc2ZlcnJpbmcgdGhlICoqYDIwMTR0YWJzZXFzLnR4dGAqKiBhbmQgdGhlICoqYDIwMTRfYmlvbV9ub19zaW5nbGV0b25zLnR4dGAqKiBmaWxlcyB0byBhIHdvcmtpbmcgZGlyZWN0b3J5IG91dHNpZGUgb2YgdGhlIFFJSU1FIHN5c3RlbSwgd2UgdXNlZCBzZXZlcmFsIFIgcGFja2FnZXMgdG8gYXNzaWduIHRheG9ub215IGFuZCBmaWx0ZXIgb3V0IHVud2FudGVkIHJldHVybnMsIHN1Y2ggYXMgbG93IHNpbWlsYXJpdHkgbWF0Y2hlcyBhbmQgdGhvc2Ugb3V0c2lkZSBhIHJlYXNvbmFibGUgZ2VvZ3JhcGhpYyBhcmVhLiANCg0KIyMjI1RoZSBmb2xsb3dpbmcgc2VjdGlvbnMgdXNlIHRoZSBvdXRwdXQgZmlsZXMgZnJvbSB0aGUgW0lsbHVtaW5hIE1pc2VxXSgjSWxsdW1pbmEgTWlTZXEpIHNlY3Rpb24gYWJvdmUuIElmIHlvdSBvbmx5IGhhdmUgb3V0cHV0IGZyb20gdGhlIFtJb24gVG9ycmVudF0oI0lvbiBUb3JyZW50KSBzZWN0aW9uLCB1c2UgKipgMjAxNGlvbnRhYnNlcXMudHh0YCoqIGFuZCAqKmAyMDE0X2lvbl9iaW9tX25vX3NpbmdsZXRvbnMudHh0YCoqDQo8YnI+DQoNCiMjIyAqKjEpKiogUlN0dWRpbyBhbmQgUiBOb3RlYm9va3MNCiMjIyMgVG8gZWRpdCBzb3VyY2UgY29kZSBvciB0byBydW4gZWFjaCBzdGVwIGFuZCBmb2xsb3cgdGhlIHR1dG9yaWFsLCB0aGUgZWFzaWVzdCBtZXRob2QgaXMgdG8gb3BlbiB0aGUgcHJvdmlkZWQgLlJtZCAoUiBNYXJrZG93bikgZmlsZSBpbiBSU3R1ZGlvOiBodHRwczovL3d3dy5yc3R1ZGlvLmNvbS9wcm9kdWN0cy9yc3R1ZGlvL2Rvd25sb2FkLy4NCiMjIyNXZSB1c2VkIFJTdHVkaW8gVmVyc2lvbiAxLjAuMTM2IC0tIKkgMjAwOS0yMDE2IFJTdHVkaW8sIEluYy4gUHJvZ3JhbSBSIG11c3QgZmlyc3QgYmUgaW5zdGFsbGVkIG9uIHRoZSBzYW1lIG1hY2hpbmU6IGh0dHBzOi8vd3d3LnItcHJvamVjdC5vcmcvLiBXZSB1c2VkIFIgdmVyc2lvbiAzLjMuMiAoMjAxNi0xMC0zMSkgLS0gIlNpbmNlcmUgUHVtcGtpbiBQYXRjaCIuIEFsbCByZW1haW5pbmcgZGF0YSBwcm9jZXNzaW5nIHN0ZXBzIGluIHRoaXMgc2VjdGlvbiBzaG91bGQgYmUgcnVuIGluIFJTdHVkaW8uDQpgYGB7cn0NCmluc3RhbGwucGFja2FnZXMoJ3JtYXJrZG93bicpDQpsaWJyYXJ5ICgncm1hcmtkb3duJykNCmBgYA0KPGJyPg0KDQojIyMgKioyKSoqIFNldCBXb3JraW5nIERpcmVjdG9yeSBhbmQgUmVhZCBpbiBEYXRhDQojIyMjIENoYW5nZSBkaXJlY3RvcnkgcGF0aCBhcyBuZWVkZWQuDQpgYGB7ciwgZWNobz1UUlVFLCBldmFsPVRSVUV9DQpzZXR3ZCgiQzpcXFVzZXJzXFxPd25lclxcR29vZ2xlIERyaXZlXFxJT052c01JU0VRIikNCg0KbXlkYXRhIDwtIHJlYWQudGFibGUoIjIwMTRpb250YWJzZXFzLnR4dCIsIGhlYWRlciA9IFRSVUUsIHNlcCA9ICJcdCIsIGRlYyA9ICIuIiwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KDQpoZWFkKG15ZGF0YSkNCg0KbXlkYXRhMiA8LSBhcy5saXN0KHNldE5hbWVzKG15ZGF0YSRzZXFzLCBteWRhdGEkc2VxSUQpKSAgI21ha2Ugc3VyZSBoZWFkZXJzIGFyZSBub3QgY2FwaXRhbGl6ZWQNCmBgYA0KPGJyPg0KDQojIyMgKiozKSoqIFF1ZXJ5IEJPTEQgZm9yIE9UVSBNYXRjaGVzDQojIyMjVXNlIHRoZSAqKmBib2xkX2lkZW50aWZ5YCoqIGZ1bmN0aW9uIHRvIGdldCBzZXF1ZW5jZXMgZnJvbSB0aGUgQk9MRCBBUEkuIFRoaXMgd2lsbCByZXR1cm4gYWxsIHRoZSBtYXRjaGVzIGluIEJPTEQsIHdoaWNoIHNob3VsZCBhbHNvIGluY2x1ZGUgc2VxdWVuY2VzIG1pbmVkIGZyb20gR2VuQmFuayAoaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9nZW5iYW5rLykuDQpgYGB7ciwgZWNobz1UUlVFfQ0KaW5zdGFsbC5wYWNrYWdlcygnYm9sZCcpDQoNCmxpYnJhcnkoYm9sZCkNCg0Kb3V0cHV0IDwtIGJvbGRfaWRlbnRpZnkoc2VxdWVuY2VzID0gbXlkYXRhMiwgZGIgPSAiQ09YMSIsIHJlc3BvbnNlPUZBTFNFKSAjVGhpcyBjYW4gdGFrZSBzZXZlcmFsIGhvdXJzIHRvIHJ1bg0KYGBgDQo8YnI+DQoNCiMjIyAqKjQpKiogVHJpbSBPdXRwdXQgYnkgVXNlci1zcGVjaWZpYyBOdW1iZXIgb2YgTWF0Y2hlcw0KIyMjIyBXZSB0cmltbWVkIG91ciBvdXRwdXQgdG8gdGhlIHRvcCA0MCBtYXRjaGVzIGZvciBlYWNoIE9UVTsgdGhpcyBudW1iZXIgY2FuIHZhcnkgZGVwZW5kaW5nIG9uIHByb2plY3Qgb2JqZWN0aXZlcy4gSW4gbWFueSBjYXNlcyB0aGVyZSB3aWxsIGJlIHVwIHRvIDEwMCBtYXRjaGVzIGZvciBlYWNoIE9UVS4gUmVzdWx0cyBtaW5lZCBmcm9tIEdlbkJhbmsgYXJlIG9ubHkgcmV0dXJuZWQgYXQgdGhlIE9yZGVyIGxldmVsIGFuZCByZXF1aXJlIGZ1cnRoZXIgaW52ZXN0aWdhdGlvbiBpbiB0aGUgW01hbnVhbCBWZXR0aW5nIG9mIFJlc3VsdHNdIHNlY3Rpb24uIEZvciBvdXIgZGF0YSwgdHJpbW1pbmcgdG8gdGhlIDQwIHRvcCBtYXRjaGVzIGxlZnQgZW5vdWdoIHNlcXVlbmNlcyB0byByZXNvbHZlIGRpc2NyZXBhbmNpZXMgd2hpbGUgYWxzbyByZW1vdmluZyBleHRyYW5uZW91cyByZXN1bHRzLCB1bHRpbWF0ZWx5IG1ha2luZyBpdCBlYXNpZXIgdG8gcGFyc2UgdGhyb3VnaCBlYWNoIE9UVSBhbmQgYXNzaWduIHRheG9ub215Lg0KYGBge3IsIGVjaG89VFJVRX0NCm91dHRheDQwIDwtIGxhcHBseShvdXRwdXQsIGhlYWQsIG49NDApDQoNCm91dHRheGZyYW1lIDwtIGRvLmNhbGwoInJiaW5kIiwgbGFwcGx5KG91dHRheDQwLCBkYXRhLmZyYW1lKSkNCmBgYA0KIyMjI1RoZSAqKmBvdXR0YXhmcmFtZWAqKiByZXR1cm5zIHRoZSB0b3AgNDAgbWF0Y2hlcywgYnkgc2ltaWxhcml0eSwgZnJvbSB0aGUgQk9MRCByZXN1bHRzLg0KPGJyPg0KDQojIyMgKio1KSoqIEZpbHRlciBvdXQgU2VxcyA8IDk4JSBhbmQgVW5saWtlbHkgYnkgR2VvZ3JhcGh5DQojIyMjVGhpcyBzdGVwIG5vdCBvbmx5IGZpbHRlcnMgb3V0IGxvdyBwZXJjZW50IHNpbWlsYXJpdHkgbWF0Y2hlcywgYnV0IGFsc28gaGVscHMgd2l0aCBkaXNjcmVwYW5jeSByZXNvbHV0aW9uIHdoZW4gc2V2ZXJhbCBzcGVjaW1lbnMgZnJvbSBCT0xEIG1hdGNoIG9uZSBPVFUgYXQgdGhlIHNhbWUgc2ltaWxhcml0eS4NCg0KIyMjI1dlIG9ubHkga2VwdCBtYXRjaGVzIHRoYXQgd2VyZSA+IDk4LjQlIGJ1dCBvdGhlciBzdHVkaWVzIGhhdmUgdXNlZCBsb3dlciAlIHNpbWlsYXJpdGllcy4gV2l0aG91dCB0aGlzIGZpbHRlcmluZyBzdGVwIGl0IHRha2VzIG11Y2ggbG9uZ2VyIHRvIGFzc2lnbiB0YXhvbm9teSB3aXRoIG1hbnVhbCB2ZXR0aW5nIG9mIG1hdGNoZXMgYnkgZ2VvZ3JhcGhpYyBhcmVhLiBGb3IgZXhhbXBsZSwgZXZlbiBhdCA+IDk4LjQlIHNpbWlsYXJpdHksIGl0IGlzIHBvc3NpYmxlIGZvciBvbmUgT1RVIHRvIG1hdGNoIGEgbW90aCBzcGVjaW1lbiBmcm9tIHRoZSBVU0EgKiphbmQqKiBhIGJ1dHRlcmZseSBmcm9tIFBhcHVhIE5ldyBHdWluZWEuDQoNCmBgYHtyLCBlY2hvPVRSVUV9DQojV2UgdXNlZCBhIGN1c3RvbSBoZWFkZXIgc3R5bGUgZm9yIHRoZSBmaW5hbCB4bHN4IGZpbGUNCkhTIDwtIGNyZWF0ZVN0eWxlKGZvbnRTaXplPTEzLCBmb250Q29sb3VyPSduYXZ5JywgbnVtRm10PSdHRU5FUkFMJywgaGFsaWduPSdjZW50ZXInLCB2YWxpZ249J2NlbnRlcicsIHRleHREZWNvcmF0aW9uPSdib2xkJywgd3JhcFRleHQ9VFJVRSkNCmBgYA0KDQpgYGB7ciwgZWNobz1UUlVFfQ0KaW5zdGFsbC5wYWNrYWdlcygnb3Blbnhsc3gnKQ0KaW5zdGFsbC5wYWNrYWdlcygnZHBseXInKQ0KDQpsaWJyYXJ5KG9wZW54bHN4KSAgICAgI011c3QgaGF2ZSBSdG9vbHMgaW5zdGFsbGVkIGFuZCBjaGVjayBib3ggdG8gZWRpdCBQQVRIIG9yIGFmdGVyd2FyZHMgZG86IFN5cy5zZXRlbnYoIlJfWklQQ01EIiA9ICJDOi9SdG9vbHMvYmluL3ppcC5leGUiKSAjI3BhdGggdG8gemlwLmV4ZQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkodGliYmxlKQ0KDQpvdXR0YXhmcmFtZSAlPD4lICAgICAjVGhpcyBvbmx5IGtlZXBzIHJvd3MgdGhhdCB3ZSB3YW50IGFuZCB1cGRhdGVzIHRoZSBkYXRhZnJhbWUNCglyb3duYW1lc190b19jb2x1bW4oInNlcUlEIikgJT4lICAgICANCglmaWx0ZXIoc3BlY2ltZW5fY291bnRyeSAlaW4lIGMoIlVuaXRlZCBTdGF0ZXMiLCAiQ2FuYWRhIiksIHNpbWlsYXJpdHkgPj0gMC45OCkNCg0Kd3JpdGUueGxzeChvdXR0YXhmcmFtZSwgZmlsZT0nMjAxNG91dHRheGZyYW1lNDAueGxzeCcsIGFzVGFibGU9RkFMU0UsIGNvbE5hbWVzPVRSVUUsIHJvd05hbWVzPVRSVUUsIGhlYWRlclN0eWxlPUhTKQ0KDQogICAgICNNaWdodCBnZXQgYW4gZXJyb3IgaWYgUnRvb2xzIGlzIG5vdCBpbnN0YWxsZWQgLSBmb2xsb3cgZXJyb3IgbWVzc2FnZSBzdWdnZXN0aW9ucyB0byBnZXQgUnRvb2xzDQpgYGANCiMjIyNUaGUgZmluYWwgZmlsdGVyZWQgZmlsZSBzaG91bGQgbG9vayBsaWtlIHRoaXMsIHdpdGggdXAgdG8gNDAgcmVjb3JkcyBmb3IgZWFjaCBkZW5vdm8gT1RVOg0KYGBge3IsIGVjaG89RkFMU0UsIGV2YWw9VFJVRX0NCmxpYnJhcnkob3Blbnhsc3gpIA0KbXlkYXRhMiA8LSByZWFkLnhsc3goIkM6XFxVc2Vyc1xcT3duZXJcXEdvb2dsZSBEcml2ZVxcRGlzc19wcm9wb3NhbFxccHJleUlEc1xcMjAxNElvblxcMjAxNG91dHRheGZyYW1lNDAueGxzeCIsIGNvbE5hbWVzID0gVFJVRSkNCmBgYA0KDQo8ZGl2IGNsYXNzPSJ0YWJsZSI+DQpgYGB7ciwgZWNobz1GQUxTRSwgcmVzdWx0cz0nYXNpcycsIGV2YWw9VFJVRX0NCmxpYnJhcnkoJ2tuaXRyJykNCmthYmxlKGhlYWQobXlkYXRhMikpDQpgYGANCg0KPGJyPg0KDQojPGEgaWQ9Ik1hbnVhbCBWZXR0aW5nIj48L2E+TWFudWFsIFZldHRpbmcgb2YgUmVzdWx0cyAtLSBfX19Xb3JrIGluIGEgV2ViIEJyb3dzZXJfX18NCg0KIyMjI1RoZSAzIGZpbGVzIG9mIGludGVyZXN0IGZvciBhc3NpZ25pbmcgZmluYWwgdGF4b25vbXkgYXJlOiAqKmAyMDE0b3V0dGF4ZnJhbWU0MC54bHN4YCoqLCAqKmAyMDE0dGFic2Vxcy50eHRgKiosIGFuZCAqKmAyMDE0ZmluYWxfbm9fc2luZ2xldG9ucy50eHRgKiouDQoNCiMjIyNGaXJzdCwgd2Ugb3BlbiB0aGUgKipgMjAxNGJpb21fbm9fc2luZ2xldG9ucy50eHRgKiogZmlsZSBhbmQgY29udmVydCBhbnkgd2l0aGluLXNhbXBsZSBvY2N1cnJlbmNlcyA8IDEwIHRvIDAgdG8gcmVtb3ZlIGxvdyBhYnVuZGFuY2UgT1RVIG9jY3VycmVuY2VzIHdpdGggc2ltcGxlIGZpbmQgYW5kIHJlcGxhY2UgY29tbWFuZHMgaW4gTVMgRXhjZWwuIFRoaXMgc3RlcCBpcyB0byByZW1vdmUgcG90ZW50aWFsIHNlcXVlbmNpbmcgZXJyb3JzOyB0aGUgdGhyZXNob2xkIG9mIDEwIGlzIGFyYml0cmFyeSBhbmQgY2FuIGJlIGNoYW5nZWQgZGVwZW5kaW5nIG9uIHByb2plY3Qgb2JqZWN0aXZlcy4gDQoNCiMjIyNOZXh0LCB3ZSBvcGVuICoqYDIwMTRvdXR0YXhmcmFtZTQwLnhsc3hgKiogYW5kICwgYW5kIGxvb2sgZm9yIGFueSBkaXNjcmVwYW5jaWVzIGF0IHRoZSBzYW1lIHNpbWlsYXJpdHkgaW4gb3VyIG91dHB1dCBmcm9tICoqYGJvbGRfaWRlbnRpZnlgKiosIGFuZCB0aGVuIGFzc2lnbiB0YXhvbm9teSBpbiBuZXcgY29sdW1ucyBpbiB0aGUgKipgMjAxNGZpbmFsX25vX3NpbmdsZXRvbnMudHh0YCoqIGZpbGUuDQoNCiMjIypVcGRhdGluZyB0aGUgQklPTSB0YWJsZSB3aXRoIFRheG9ub215Kg0KIVtdKEM6XFxVc2Vyc1xcT3duZXJcXEdvb2dsZSBEcml2ZVxcSU9OdnNNSVNFUVxcQmF0RGlldFdvcmtmbG93X2ZpbGVzXFxmaXJzdExvb2sucG5nKSANCg0KPGJyPg0KDQojIyMjU29tZXRpbWVzIHRoZXJlIGFyZSBkaXNjcmVwYW5jaWVzIGluIHRoZSByZXN1bHRzIHJldHVybmVkIGZyb20gKipgYm9sZF9pZGVudGlmeWAqKiB0aGF0IHdlIG5lZWQgdG8gbWFudWFsbHkgaW52ZXN0aWdhdGUuDQoNCiMjIyNJbiB0aGlzIGV4YW1wbGUsIHJlc3VsdHMgZm9yIE9UVSBkZW5vdm8xMTggbWF0Y2ggNiBkaWZmZXJlbnQgc3BlY2llcyBpbiB0aGUgc2FtZSBnZW51cyBhdCAxMDAlLiBXZSBrbm93IHRoYXQgYWxsIG9mIHRoZXNlIG1hdGNoaW5nIHNwZWNpbWVuIHJlY29yZHMgY291bGQgb2NjdXIgd2l0aGluIG91ciByZWdpb24gYmVjYXVzZSB3ZSBmaWx0ZXJlZCB0aGUgKipgMjAxNG91dHRheGZyYW1lNDAueGxzeGAqKiBiYXNlZCBvbiBzaW1pbGFyaXR5ICphbmQqIGdlb2dyYXBoeS4gTm9uZXRoZWxlc3MsIHdlIGNob3NlIGEgc2ltcGxlIGV4YW1wbGUgdG8gZGVtb25zdHJhdGUgdGhlIHByb2Nlc3Mgb2YgaG93IHdlIGxlYXJuZWQgdG8gY29udmVydCByZXN1bHRzIGludG8gYXNzaWduZWQgdGF4b25vbXkuDQoNCiMjIypEaXNjcmVwYW5jeSBFeGFtcGxlKg0KIVtdKEM6XFxVc2Vyc1xcT3duZXJcXEdvb2dsZSBEcml2ZVxcSU9OdnNNSVNFUVxcQmF0RGlldFdvcmtmbG93X2ZpbGVzXFxkaXNjcmVwYW5jeWV4LmpwZykgDQoNCjxicj4NCg0KIyMjI05leHQsIHdlIGdvIHRvIG91ciAqKmAyMDE0dGFic2Vxcy50eHRgKiogZmlsZSB0byBmaW5kIHRoZSBzZXF1ZW5jZSBmb3IgZGVub3ZvMTE4DQoNCiMjIypGaW5kIHRoZSBTZXF1ZW5jZSBpbiBRdWVzdGlvbioNCiFbXShDOlxcVXNlcnNcXE93bmVyXFxHb29nbGUgRHJpdmVcXElPTnZzTUlTRVFcXEJhdERpZXRXb3JrZmxvd19maWxlc1xcZmluZHRoZXNlcS5qcGcpDQoNCjxicj4NCg0KIyMjI1dlIGN1dCBhbmQgcGFzdGUgdGhlIHNlcXVlbmNlIGludG8gdGhlIEJPTEQgSWRlbnRpZmljYXRpb24gYnJvd3NlciBpbiBGQVNUQSBmb3JtYXQgKGh0dHA6Ly93d3cuYm9sZHN5c3RlbXMub3JnL2luZGV4LnBocC9JRFNfT3BlbklkRW5naW5lKQ0KDQojIyMqUGFzdGUgU2VxdWVuY2UgaW50byBCT0xEKg0KIVtdKEM6XFxVc2Vyc1xcT3duZXJcXEdvb2dsZSBEcml2ZVxcSU9OdnNNSVNFUVxcQmF0RGlldFdvcmtmbG93X2ZpbGVzXFxwYXN0ZVNlcS5qcGcpDQoNCjxicj4NCg0KIyMjI1dlIGdldCBtYW55IG1hdGNoZXMgYXQgMTAwJSwgaW5jbHVkaW5nIHNvbWUgb3V0IG9mIG91ciBhcmVhLiBUaGVyZSBhcmUgc2V2ZXJhbCAqQ2F0b2NhbGEgc3BwLiosIGFzIGV4cGVjdGVkLiBXZSBkb24ndCBleHBlY3QgYW55IE55bXBoYWxpZGFlIGJ1dHRlcmZsaWVzIGluIGJhdCBmZWNlcyBzbyB3ZSBkaXNyZWdhcmQgdGhvc2UuIFRoYXQgbGVhdmVzICpQaWxldG9jZXJhIHNvZGFsaXMqIGFzIGFub3RoZXIgcG90ZW50aWFsIHByZXkuIA0KDQojIyMqUmUtZXhhbWluZSB0aGUgTWF0Y2hlcyoNCiFbXShDOlxcVXNlcnNcXE93bmVyXFxHb29nbGUgRHJpdmVcXElPTnZzTUlTRVFcXEJhdERpZXRXb3JrZmxvd19maWxlc1xcaWRSZXF1ZXN0LmpwZykNCg0KPGJyPg0KDQojIyMjV2hlbiB3ZSBpbnZlc3RpZ2F0ZSAqUGlsZXRvY2VyYSBzb2RhbGlzKiBpbiB0aGUgQk9MRCBUYXhvbm9teSBicm93c2VyLCB3ZSBsZWFybiB0aGF0IGl0IGlzIG9ubHkgZm91bmQgaW4gSmFwYW4sIENoaW5hLCBhbmQgS29yZWEsIHNvIHdlIGRpc3JlZ2FyZCB0aGF0IHBvdGVudGlhbCBwcmV5LiBCZWNhdXNlIHdlIHN0aWxsIGhhdmUgNiAqQ2F0b2NhbGEgc3BwLiogcG9zc2libGUsIHdlIGNhbiBvbmx5IGFzc2lnbiB0YXhvbm9teSB0byBPVFUgZGVub3ZvMTE4IGFzICpDYXRvY2FsYSBzcHAuKg0KDQojIyMqQ3Jvc3MtcmVmZXJlbmNlIHdpdGggRXhwZWN0YXRpb25zKg0KIVtdKEM6XFxVc2Vyc1xcT3duZXJcXEdvb2dsZSBEcml2ZVxcSU9OdnNNSVNFUVxcQmF0RGlldFdvcmtmbG93X2ZpbGVzXFxtb3RoT3V0b2ZBcmVhLmpwZykNCg==